diff --git a/apps/dashboard/src/app/(dashboard)/layout.tsx b/apps/dashboard/src/app/(dashboard)/layout.tsx
index 94e2a92..633f33a 100644
--- a/apps/dashboard/src/app/(dashboard)/layout.tsx
+++ b/apps/dashboard/src/app/(dashboard)/layout.tsx
@@ -4,18 +4,20 @@ import TopBar from '@/components/layout/TopBar'
export default function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
-
-
-
-
-
+
)
}
diff --git a/production/dynamic/mail-certificate.yml b/production/dynamic/mail-certificate.yml
new file mode 100644
index 0000000..ab08614
--- /dev/null
+++ b/production/dynamic/mail-certificate.yml
@@ -0,0 +1,18 @@
+http:
+ routers:
+ mail-certificate:
+ rule: "Host(`mail.rentaldrivego.ma`)"
+ entryPoints:
+ - websecure
+ service: mail-certificate-placeholder
+ tls:
+ certResolver: letsencrypt
+ domains:
+ - main: "mail.rentaldrivego.ma"
+ services:
+ mail-certificate-placeholder:
+ loadBalancer:
+ servers:
+ # This router exists to request and renew the certificate.
+ # Mail protocols are not routed through this HTTP service.
+ - url: "http://127.0.0.1:65535"
diff --git a/production/traefik.yaml b/production/traefik.yaml
index e6fd4dc..2fa614f 100644
--- a/production/traefik.yaml
+++ b/production/traefik.yaml
@@ -1,6 +1,8 @@
services:
traefik:
- image: traefik:latest
+ # Set TRAEFIK_VERSION in .env to the exact version you are running.
+ # Do not use "latest" in production.
+ image: traefik:${TRAEFIK_VERSION}
command:
- --api.dashboard=false
- --api.insecure=false
@@ -29,6 +31,51 @@ services:
- ./dynamic:/etc/traefik/dynamic:ro
networks:
- traefik-proxy
+
+ traefik-certs-dumper:
+ image: ldez/traefik-certs-dumper:v2.11.4
+ depends_on:
+ - traefik
+ restart: unless-stopped
+ # Wait for Traefik's ACME storage, then export certificates whenever
+ # acme.json changes.
+ entrypoint:
+ - /bin/sh
+ - -ec
+ command:
+ - |
+ until [ -s /data/acme.json ]; do
+ sleep 2
+ done
+
+ exec traefik-certs-dumper file \
+ --version v3 \
+ --watch \
+ --source /data/acme.json \
+ --dest /output \
+ --domain-subdir \
+ --crt-name fullchain \
+ --key-name privkey \
+ --crt-ext .pem \
+ --key-ext .pem
+ volumes:
+ # Existing Traefik ACME volume, mounted read-only.
+ - traefik-letsencrypt:/data:ro
+
+ # Normal certificate files will appear on the VPS here.
+ - ./exported-certs:/output
+ # The dumper only reads a local volume and writes exported files.
+ # It needs no network access.
+ network_mode: none
+ labels:
+ - "traefik.enable=false"
+ security_opt:
+ - no-new-privileges:true
+ cap_drop:
+ - ALL
+ read_only: true
+ tmpfs:
+ - /tmp:size=16m,mode=1777
networks:
traefik-proxy:
external: true