@maildock/mailctl 0.1.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ # Bootstrap config only: serves the Setup Wizard and API over plain HTTP until setup provides a hostname and
2
+ # TLS mode, after which the API pushes the full JSON config through the admin endpoint
3
+ # (packages/engine-postfix-dovecot/src/caddy.ts) — same routing, plus TLS.
4
+ {
5
+ admin 0.0.0.0:2019 {
6
+ origins caddy:2019 localhost:2019 127.0.0.1:2019
7
+ }
8
+ auto_https off
9
+ }
10
+ :80 {
11
+ handle /api/* {
12
+ reverse_proxy api:3000
13
+ }
14
+ handle {
15
+ reverse_proxy web:8080
16
+ }
17
+ }
@@ -0,0 +1,176 @@
1
+ # Mail server stack. Used unchanged for local development, CI smoke and customer installs (`mailctl install`);
2
+ # only `.env` differs (secrets, ports, paths, image tag — ADR 0005). Daemon configuration is rendered by the API
3
+ # into the `mailconfig` volume and applied by the in-container config watcher (ADR 0006).
4
+ name: mailserver
5
+ services:
6
+ postgres:
7
+ image: postgres:16-alpine
8
+ environment:
9
+ POSTGRES_USER: ${DB_ADMIN_USER:-mail}
10
+ POSTGRES_PASSWORD: ${DB_ADMIN_PASSWORD:-mail}
11
+ POSTGRES_DB: ${DB_NAME:-mail}
12
+ volumes: [pgdata:/var/lib/postgresql/data]
13
+ ports: ['${DB_BIND:-127.0.0.1}:${DB_PORT:-5432}:5432']
14
+ healthcheck:
15
+ test: ['CMD-SHELL', 'pg_isready -U ${DB_ADMIN_USER:-mail} -d ${DB_NAME:-mail}']
16
+ interval: 5s
17
+ timeout: 3s
18
+ retries: 10
19
+ restart: unless-stopped
20
+
21
+ redis:
22
+ image: redis:7-alpine
23
+ command: ['redis-server', '--save', '', '--appendonly', 'no']
24
+ healthcheck:
25
+ test: ['CMD', 'redis-cli', 'ping']
26
+ interval: 5s
27
+ timeout: 3s
28
+ retries: 10
29
+ restart: unless-stopped
30
+
31
+ rspamd:
32
+ image: ${IMAGE_REGISTRY:-mailserver}/rspamd:${IMAGE_TAG:-dev}
33
+ build: { context: ../docker, dockerfile: rspamd/Dockerfile }
34
+ depends_on:
35
+ redis: { condition: service_healthy }
36
+ volumes: [mailconfig:/var/lib/mailserver/config]
37
+ healthcheck:
38
+ test: ['CMD-SHELL', 'rspamadm control stat >/dev/null 2>&1 || exit 1']
39
+ interval: 10s
40
+ timeout: 5s
41
+ retries: 6
42
+ restart: unless-stopped
43
+
44
+ dovecot:
45
+ image: ${IMAGE_REGISTRY:-mailserver}/dovecot:${IMAGE_TAG:-dev}
46
+ build: { context: ../docker, dockerfile: dovecot/Dockerfile }
47
+ environment:
48
+ DB_HOST: postgres
49
+ DB_NAME: ${DB_NAME:-mail}
50
+ DB_USER: ${DB_DAEMON_USER:-mail_daemon}
51
+ DB_PASSWORD: ${DB_DAEMON_PASSWORD:-change-me-at-install}
52
+ MASTER_USER: mailserver-api
53
+ MASTER_PASSWORD: ${DOVECOT_MASTER_PASSWORD:-change-me-at-install}
54
+ volumes:
55
+ - vmail:/var/vmail
56
+ - mailconfig:/var/lib/mailserver/config
57
+ - certs:/certs:ro
58
+ ports:
59
+ - '${IMAP_PORT:-143}:143'
60
+ - '${IMAPS_PORT:-993}:993'
61
+ - '${POP3_PORT:-110}:110'
62
+ - '${POP3S_PORT:-995}:995'
63
+ - '${SIEVE_PORT:-4190}:4190'
64
+ depends_on:
65
+ postgres: { condition: service_healthy }
66
+ cert-sync: { condition: service_started }
67
+ restart: unless-stopped
68
+
69
+ postfix:
70
+ image: ${IMAGE_REGISTRY:-mailserver}/postfix:${IMAGE_TAG:-dev}
71
+ build: { context: ../docker, dockerfile: postfix/Dockerfile }
72
+ hostname: ${MAIL_HOSTNAME:-mail.example.test}
73
+ environment:
74
+ SRS_SECRET: ${SRS_SECRET:-change-me-at-install}
75
+ MAIL_HOSTNAME: ${MAIL_HOSTNAME:-mail.example.test}
76
+ DB_HOST: postgres
77
+ DB_NAME: ${DB_NAME:-mail}
78
+ DB_USER: ${DB_DAEMON_USER:-mail_daemon}
79
+ DB_PASSWORD: ${DB_DAEMON_PASSWORD:-change-me-at-install}
80
+ volumes:
81
+ - maillog:/var/log/mail
82
+ - vmail:/var/vmail
83
+ - mailconfig:/var/lib/mailserver/config
84
+ - certs:/certs:ro
85
+ ports:
86
+ - '${SMTP_PORT:-25}:25'
87
+ - '${SMTPS_PORT:-465}:465'
88
+ - '${SUBMISSION_PORT:-587}:587'
89
+ depends_on:
90
+ postgres: { condition: service_healthy }
91
+ dovecot: { condition: service_started }
92
+ rspamd: { condition: service_started }
93
+ restart: unless-stopped
94
+
95
+ api:
96
+ image: ${IMAGE_REGISTRY:-mailserver}/api:${IMAGE_TAG:-dev}
97
+ build: { context: .., dockerfile: docker/api/Dockerfile }
98
+ environment:
99
+ DATABASE_URL: postgres://${DB_ADMIN_USER:-mail}:${DB_ADMIN_PASSWORD:-mail}@postgres:5432/${DB_NAME:-mail}
100
+ JWT_SECRET: ${JWT_SECRET:-dev-only-secret-change-me-please-32chars!!}
101
+ DOVECOT_MASTER_USER: mailserver-api
102
+ DOVECOT_MASTER_PASSWORD: ${DOVECOT_MASTER_PASSWORD:-change-me-at-install}
103
+ APP_VERSION: ${IMAGE_TAG:-dev}
104
+ PUBLIC_IP: ${PUBLIC_IP:-}
105
+ COOKIE_SECURE: ${COOKIE_SECURE:-true}
106
+ LOG_LEVEL: ${LOG_LEVEL:-info}
107
+ volumes:
108
+ - mailconfig:/var/lib/mailserver/config
109
+ - certs:/certs
110
+ ports: ['${API_BIND:-127.0.0.1}:${API_PORT:-3000}:3000']
111
+ depends_on:
112
+ postgres: { condition: service_healthy }
113
+ restart: unless-stopped
114
+
115
+ worker:
116
+ image: ${IMAGE_REGISTRY:-mailserver}/worker:${IMAGE_TAG:-dev}
117
+ build: { context: .., dockerfile: docker/worker/Dockerfile }
118
+ environment:
119
+ DATABASE_URL: postgres://${DB_ADMIN_USER:-mail}:${DB_ADMIN_PASSWORD:-mail}@postgres:5432/${DB_NAME:-mail}
120
+ REDIS_URL: redis://redis:6379
121
+ PUBLIC_IP: ${PUBLIC_IP:-}
122
+ DNS_CHECK_INTERVAL_MINUTES: ${DNS_CHECK_INTERVAL_MINUTES:-15}
123
+ REPUTATION_CHECK_INTERVAL_MINUTES: ${REPUTATION_CHECK_INTERVAL_MINUTES:-60}
124
+ DMARC_INGEST_INTERVAL_MINUTES: ${DMARC_INGEST_INTERVAL_MINUTES:-30}
125
+ DELIVERY_LOG_RETENTION_DAYS: ${DELIVERY_LOG_RETENTION_DAYS:-30}
126
+ DOVECOT_MASTER_USER: mailserver-api
127
+ DOVECOT_MASTER_PASSWORD: ${DOVECOT_MASTER_PASSWORD:-change-me-at-install}
128
+ LOG_LEVEL: ${LOG_LEVEL:-info}
129
+ volumes:
130
+ - maillog:/var/log/mail
131
+ - certs:/certs:ro
132
+ depends_on:
133
+ api: { condition: service_healthy }
134
+ redis: { condition: service_healthy }
135
+ dovecot: { condition: service_healthy }
136
+ restart: unless-stopped
137
+
138
+ web:
139
+ image: ${IMAGE_REGISTRY:-mailserver}/web:${IMAGE_TAG:-dev}
140
+ build: { context: .., dockerfile: docker/web/Dockerfile }
141
+ restart: unless-stopped
142
+
143
+ caddy:
144
+ image: caddy:2-alpine
145
+ volumes:
146
+ - ../docker/caddy/Caddyfile:/etc/caddy/Caddyfile:ro
147
+ - caddy_data:/data
148
+ - caddy_config:/config
149
+ - certs:/certs:ro
150
+ ports:
151
+ - '${HTTP_PORT:-80}:80'
152
+ - '${HTTPS_PORT:-443}:443'
153
+ depends_on:
154
+ api: { condition: service_started }
155
+ web: { condition: service_started }
156
+ restart: unless-stopped
157
+
158
+ cert-sync:
159
+ image: ${IMAGE_REGISTRY:-mailserver}/cert-sync:${IMAGE_TAG:-dev}
160
+ build: ../docker/cert-sync
161
+ environment:
162
+ MAIL_HOSTNAME: ${MAIL_HOSTNAME:-mail.example.test}
163
+ volumes:
164
+ - caddy_data:/caddy-data:ro
165
+ - certs:/certs
166
+ - mailconfig:/var/lib/mailserver/config
167
+ restart: unless-stopped
168
+
169
+ volumes:
170
+ pgdata:
171
+ maillog:
172
+ vmail:
173
+ mailconfig:
174
+ certs:
175
+ caddy_data:
176
+ caddy_config:
package/bin/dev.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env -S node --import tsx
2
+ import { execute } from '@oclif/core';
3
+ await execute({ development: true, dir: import.meta.url });
package/bin/run.js ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ import { execute } from '@oclif/core';
3
+ await execute({ dir: import.meta.url });
@@ -0,0 +1,4 @@
1
+ // Generated by scripts/bundle.mjs. mailctl is consumed as a binary; these are the exported
2
+ // helpers only.
3
+ export declare const PACKAGE_NAME: '@maildock/mailctl';
4
+ export declare const COMMANDS: Record<string, unknown>;