+
+
+ Here's your .env
file:
+
+
+
+
+
+ {`
+API_DOMAIN=${apiDomain}
+MAIL_DOMAIN=${mailDomain}
+KLECK_SECRET=${privateKeys!.kleckSecret}
+SERVER_PRIVATE_KEY=${privateKeys!.serverKey}
+DKIM_PRIVATE_KEY=${privateKeys!.dkimKey}
+ADMIN_EMAILS=${admins.join(",")}
+DB_URI=postgres://kleckrelay:${privateKeys!.dbPassword}@${dockerServicesPrefix}database/kleckrelay
+ `.trimStart().trimEnd()}
+
+
+
+
+
+ Here's your docker-compose.yml
file:
+
+
+
+
+
+ {`
+version: "3"
+services:
+ ${dockerServicesPrefix}database:
+ image: postgres:latest
+ container_name: "${dockerServicesPrefix}database"
+ restart: on-failure:5
+
+ environment:
+ POSTGRES_USER: kleckrelay
+ POSTGRES_PASSWORD: ${privateKeys!.dbPassword}
+ POSTGRES_DB: kleckrelay
+
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U user -d mail"]
+ interval: 5s
+ timeout: 5s
+ retries: 5
+
+ volumes:
+ - ./db:/var/lib/postgresql/data
+
+ ${dockerServicesPrefix}server:
+ image: myzel394/kleckrelay-server:latest
+ container_name: "${dockerServicesPrefix}server"
+ restart: on-failure:5
+
+ depends_on:
+ ${dockerServicesPrefix}database:
+ condition: service_healthy
+
+ cap_add:
+ - NET_BIND_SERVICE
+ - SYS_PTRACE
+
+ ports:
+ - "25:25"
+ - "587:587"
+
+ volumes:
+ - ./tutorial:/tutorial
+ - ./opendkim_keys:/etc/opendkim/keys
+ - ./certs:/etc/ssl/certs
+
+ env_file:
+ - .env
+
+ ${dockerServicesPrefix}maid:
+ image: myzel394/kleckrelay-maid:latest
+ container_name: "${dockerServicesPrefix}maid"
+ restart: on-failure:5
+
+ depends_on:
+ ${dockerServicesPrefix}database:
+ condition: service_healthy
+
+ env_file:
+ - .env
+
+ nginx:
+ image: bunkerity/bunkerweb
+ container_name: nginx
+ restart: on-failure:5
+
+ ports:
+ - "80:80"
+ - "443:443"
+
+ volumes:
+ - ./letsencrypt:/etc/letsencrypt
+
+ environment:
+ - MULTISITE=yes
+ - SERVER_NAME=${domain}
+ - USE_REVERSE_PROXY=yes
+ - DISABLE_DEFAULT_SERVER=yes
+ - AUTO_LETS_ENCRYPT=yes
+
+ - ${domain}_REVERSE_PROXY_URL=/
+ - ${domain}_REVERSE_PROXY_HOST=${dockerServicesPrefix}server
+ - ${domain}_ALLOWED_METHODS=GET|POST|PUT|PATCH|DELETE|OPTIONS
+ # Security is too strict
+ - ${domain}_BLOCK_ABUSERS=no
+ - ${domain}_USE_BAD_BEHAVIOR=no
+ - ${domain}_REVERSE_PROXY_INTERCEPT_ERRORS=no
+`.trimStart().trimEnd()}
+
+
+
+
+ )
+ }
+
+ return (
+
+
+
+
+
+ Base Domain
+
+
+
+ {
+ setDomain(event.target.value);
+ setApiDomain(`api.${event.target.value}`);
+ setMailDomain(`mail.${event.target.value}`);
+ }}
+ />
+
+
+
+
+
+ Mail Domain
+
+
+
+ setMailDomain(e.target.value)}
+ />
+
+
+
+
+
+ API Domain
+
+
+
+ setApiDomain(e.target.value)}
+ />
+
+
+
+
+
+
+ Admins
+
+
+
+
+
+ setTempAdminValue(e.target.value)}
+ onKeyDown={event => {
+ if (event.key === "Enter" || event.key === " " || event.key === "," || event.key === ";") {
+ event.preventDefault();
+
+ if (tempAdminValue) {
+ setAdmins([...admins, tempAdminValue]);
+ setTempAdminValue("");
+ }
+ }
+ }}
+ />
+
+
+ {admins.map((admin, index) => (
+
{
+ const newAdmins = [...admins];
+ newAdmins.splice(index, 1);
+ setAdmins(newAdmins);
+ }}
+ >
+ {admin}
+
+ ))}
+
+
+
+
+
+
+
+ Docker Services Prefix
+
+
+
+ setDockerServicesPrefix(e.target.value)}
+ />
+
+
+
+ {
+ setStatus("loading");
+
+ const {privateKey: serverPrivateKey} = await openpgp.generateKey({
+ type: "ecc",
+ format: "armored",
+ userIDs: [{name: "John Smith", email: "john@example.com"}],
+ passphrase: "",
+ rsaBits: 4096,
+ })
+ const {privateKey: dkimPrivateKey} = await openpgp.generateKey({
+ type: "ecc",
+ format: "armored",
+ userIDs: [{name: "John Smith", email: "john@example.com"}],
+ passphrase: "",
+ rsaBits: 4096,
+ })
+
+ setPrivateKeys({
+ serverKey: btoa(serverPrivateKey),
+ dkimKey: btoa(dkimPrivateKey),
+ kleckSecret: cryptoRandomString({
+ length: 64,
+ type: "hex",
+ }),
+ dbPassword: cryptoRandomString({
+ length: 64,
+ type: "hex",
+ })
+ })
+ setStatus("display");
+ }}>
+ Generate config
+
+
+
+ )
+}
diff --git a/src/css/custom.css b/src/css/custom.css
index 2bc6a4c..64e5ad8 100644
--- a/src/css/custom.css
+++ b/src/css/custom.css
@@ -3,6 +3,10 @@
* bundles Infima by default. Infima is a CSS framework designed to
* work well for content-centric websites.
*/
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
/* You can override the default Infima variables here. */
:root {