merge docker-compose-based quickstart and integration tests into a single integration test

the two were so similar it made sense to just have one that tests all. saves
building docker images.
This commit is contained in:
Mechiel Lukkien 2023-07-23 23:32:02 +02:00
parent dcb0f0a82c
commit f9e261e0fb
No known key found for this signature in database
60 changed files with 300 additions and 882 deletions

5
.gitignore vendored
View file

@ -11,7 +11,6 @@
/testdata/imap/data/
/testdata/imapserverfuzz/data/
/testdata/imaptest/data/
/testdata/integration/data/
/testdata/junk/*.bloom
/testdata/junk/*.db
/testdata/queue/data/
@ -24,8 +23,8 @@
/testdata/smtpserverfuzz/data/
/testdata/store/data/
/testdata/train/
/testdata/quickstart/example-quickstart.zone
/testdata/quickstart/tmp-pebble-ca.pem
/testdata/integration/example-integration.zone
/testdata/integration/tmp-pebble-ca.pem
/cover.out
/cover.html
/.go/

View file

@ -5,7 +5,6 @@ build:
CGO_ENABLED=0 go build
CGO_ENABLED=0 go vet ./...
CGO_ENABLED=0 go vet -tags integration
CGO_ENABLED=0 go vet -tags quickstart
./gendoc.sh
(cd http && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Admin) >http/adminapi.json
(cd http && CGO_ENABLED=0 go run ../vendor/github.com/mjl-/sherpadoc/cmd/sherpadoc/*.go -adjust-function-names none Account) >http/accountapi.json
@ -26,7 +25,6 @@ test-upgrade:
check:
staticcheck ./...
staticcheck -tags integration
staticcheck -tags quickstart
GOARCH=386 CGO_ENABLED=0 go vet ./...
# having "err" shadowed is common, best to not have others
@ -47,34 +45,15 @@ fuzz:
go test -fuzz FuzzParseRecord -fuzztime 5m ./tlsrpt
go test -fuzz FuzzParseMessage -fuzztime 5m ./tlsrpt
test-integration:
docker-compose -f docker-compose-integration.yml build --no-cache --pull moxmail
-rm -r testdata/integration/data
docker-compose -f docker-compose-integration.yml run moxmail sh -c 'CGO_ENABLED=0 go test -tags integration'
docker-compose -f docker-compose-integration.yml down
# like test-integration, but in separate steps
integration-build:
docker-compose -f docker-compose-integration.yml build --no-cache --pull moxmail
integration-start:
-rm -r testdata/integration/data
-docker-compose -f docker-compose-integration.yml run moxmail /bin/bash
docker-compose -f docker-compose-integration.yml down
# run from within "make integration-start"
integration-test:
CGO_ENABLED=0 go test -tags integration
test-quickstart:
docker image build --pull -f Dockerfile -t mox_quickstart_moxmail .
docker image build --pull -f testdata/quickstart/Dockerfile.test -t mox_quickstart_test testdata/quickstart
-rm -rf testdata/quickstart/moxacmepebble/data
-rm -rf testdata/quickstart/moxmail2/data
-rm -f testdata/quickstart/tmp-pebble-ca.pem
MOX_UID=$$(id -u) docker-compose -f docker-compose-quickstart.yml run test
docker-compose -f docker-compose-quickstart.yml down --timeout 1
docker image build --pull -f Dockerfile -t mox_integration_moxmail .
docker image build --pull -f testdata/integration/Dockerfile.test -t mox_integration_test testdata/integration
-rm -rf testdata/integration/moxacmepebble/data
-rm -rf testdata/integration/moxmail2/data
-rm -f testdata/integration/tmp-pebble-ca.pem
MOX_UID=$$(id -u) docker-compose -f docker-compose-integration.yml run test
docker-compose -f docker-compose-integration.yml down --timeout 1
imaptest-build:

View file

@ -166,12 +166,10 @@ testing purposes.
- Update features & roadmap in README.md
- Write release notes, use instructions from updating.txt.
- Build and run tests with previous major Go release.
- Run all (integration) tests, including with race detector.
- Test upgrades.
- Run tests, including with race detector.
- Run integration and upgrade tests.
- Run fuzzing tests for a while.
- Deploy to test environment. Test the update instructions.
- Test localserve.
- Generate a config with quickstart, check if it results in a working setup.
- Send and receive email through the major webmail providers, check headers.
- Send and receive email with imap4/smtp clients.
- Check DNS check admin page.

View file

@ -1,19 +1,46 @@
version: '3.7'
services:
moxmail:
# todo: understand why hostname and/or domainname don't have any influence on the reverse dns set up by docker, requiring us to use our own /etc/resolv.conf...
hostname: moxmail1.mox1.example
domainname: mox1.example
build:
dockerfile: Dockerfile.moxmail
context: testdata/integration
# We run integration_test.go from this container, it connects to both mox instances.
test:
hostname: test.mox1.example
image: mox_integration_test
# We add our cfssl-generated CA (which is in the repo) and acme pebble CA
# (generated each time pebble starts) to the list of trusted CA's, so the TLS
# dials in integration_test.go succeed.
command: ["sh", "-c", "set -ex; cat /integration/tmp-pebble-ca.pem /integration/tls/ca.pem >>/etc/ssl/certs/ca-certificates.crt; go test -tags integration"]
volumes:
- ./.go:/.go
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- ./testdata/integration:/integration
- ./testdata/integration/moxsubmit.conf:/etc/moxsubmit.conf
- .:/mox
environment:
GOCACHE: /.go/.cache/go-build
depends_on:
dns:
condition: service_healthy
# moxmail2 depends on moxacmepebble, we connect to both.
moxmail2:
condition: service_healthy
postfixmail:
condition: service_healthy
localserve:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.50
# First mox instance that uses ACME with pebble.
moxacmepebble:
hostname: moxacmepebble.mox1.example
domainname: mox1.example
image: mox_integration_moxmail
environment:
MOX_UID: "${MOX_UID}"
command: ["sh", "-c", "/integration/moxacmepebble.sh"]
volumes:
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- ./testdata/integration:/integration
healthcheck:
test: netstat -nlt | grep ':25 '
interval: 1s
@ -22,17 +49,64 @@ services:
depends_on:
dns:
condition: service_healthy
postfixmail:
condition: service_healthy
localserve:
acmepebble:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.10
mailnet2:
ipv4_address: 172.28.2.10
mailnet3:
ipv4_address: 172.28.3.10
# Second mox instance, with TLS cert/keys from files.
moxmail2:
hostname: moxmail2.mox2.example
domainname: mox2.example
image: mox_integration_moxmail
environment:
MOX_UID: "${MOX_UID}"
command: ["sh", "-c", "/integration/moxmail2.sh"]
volumes:
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- ./testdata/integration:/integration
healthcheck:
test: netstat -nlt | grep ':25 '
interval: 1s
timeout: 1s
retries: 10
depends_on:
dns:
condition: service_healthy
acmepebble:
condition: service_healthy
# moxacmepebble creates tmp-pebble-ca.pem, needed by moxmail2 to trust the certificates offered by moxacmepebble.
moxacmepebble:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.20
localserve:
hostname: localserve.mox1.example
domainname: mox1.example
build:
dockerfile: Dockerfile.moxmail
context: testdata/integration
command: ["sh", "-c", "set -e; chmod o+r /etc/resolv.conf; go run . -- localserve -ip 172.28.1.60"]
volumes:
- ./.go:/.go
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- .:/mox
environment:
GOCACHE: /.go/.cache/go-build
healthcheck:
test: netstat -nlt | grep ':1025 '
interval: 1s
timeout: 1s
retries: 10
depends_on:
dns:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.60
postfixmail:
hostname: postfixmail.postfix.example
@ -54,32 +128,7 @@ services:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.20
localserve:
hostname: localserve.mox1.example
domainname: mox1.example
build:
dockerfile: Dockerfile.moxmail
context: testdata/integration
command: ["sh", "-c", "set -e; chmod o+r /etc/resolv.conf; go run . -- localserve -ip 172.28.1.50"]
volumes:
- ./.go:/.go
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- .:/mox
environment:
GOCACHE: /.go/.cache/go-build
healthcheck:
test: netstat -nlt | grep ':1025 '
interval: 1s
timeout: 1s
retries: 10
depends_on:
dns:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.50
ipv4_address: 172.28.1.70
dns:
hostname: dns.example
@ -90,7 +139,9 @@ services:
volumes:
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- ./testdata/integration:/integration
command: ["sh", "-c", "set -e; chmod o+r /etc/resolv.conf; install -m 640 -o unbound /integration/unbound.conf /integration/*.zone /etc/unbound/; unbound -d -p -v"]
# We start with a base example.zone, but moxacmepebble appends its records,
# followed by moxmail2. They restart unbound after appending records.
command: ["sh", "-c", "set -ex; ls -l /etc/resolv.conf; chmod o+r /etc/resolv.conf; install -m 640 -o unbound /integration/unbound.conf /etc/unbound/; chmod 755 /integration; chmod 644 /integration/*.zone; cp /integration/example.zone /integration/example-integration.zone; ls -ld /integration /integration/reverse.zone; unbound -d -p -v"]
healthcheck:
test: netstat -nlu | grep '172.28.1.30:53 '
interval: 1s
@ -100,6 +151,31 @@ services:
mailnet1:
ipv4_address: 172.28.1.30
# pebble is a small acme server useful for testing. It creates a new CA
# certificate each time it starts, so we go through some trouble to configure the
# certificate in moxacmepebble and moxmail2.
acmepebble:
hostname: acmepebble.example
image: docker.io/letsencrypt/pebble:v2.3.1@sha256:fc5a537bf8fbc7cc63aa24ec3142283aa9b6ba54529f86eb8ff31fbde7c5b258
volumes:
- ./testdata/integration/resolv.conf:/etc/resolv.conf
- ./testdata/integration:/integration
command: ["sh", "-c", "set -ex; mount; ls -l /etc/resolv.conf; chmod o+r /etc/resolv.conf; pebble -config /integration/pebble-config.json"]
ports:
- 14000:14000 # ACME port
- 15000:15000 # Management port
healthcheck:
test: netstat -nlt | grep ':14000 '
interval: 1s
timeout: 1s
retries: 10
depends_on:
dns:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.40
networks:
mailnet1:
driver: bridge
@ -107,15 +183,3 @@ networks:
driver: default
config:
- subnet: "172.28.1.0/24"
mailnet2:
driver: bridge
ipam:
driver: default
config:
- subnet: "172.28.2.0/24"
mailnet3:
driver: bridge
ipam:
driver: default
config:
- subnet: "172.28.3.0/24"

View file

@ -1,133 +0,0 @@
version: '3.7'
services:
# We run quickstart_test.go from this container, it connects to both mox instances.
test:
hostname: test.mox1.example
image: mox_quickstart_test
# We add our cfssl-generated CA (which is in the repo) and acme pebble CA
# (generated each time pebble starts) to the list of trusted CA's, so the TLS
# dials in quickstart_test.go succeed.
command: ["sh", "-c", "set -ex; cat /quickstart/tmp-pebble-ca.pem /quickstart/tls/ca.pem >>/etc/ssl/certs/ca-certificates.crt; go test -tags quickstart"]
volumes:
- ./.go:/.go
- ./testdata/quickstart/resolv.conf:/etc/resolv.conf
- ./testdata/quickstart:/quickstart
- .:/mox
environment:
GOCACHE: /.go/.cache/go-build
depends_on:
dns:
condition: service_healthy
# moxmail2 depends on moxacmepebble, we connect to both.
moxmail2:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.50
# First mox instance that uses ACME with pebble.
moxacmepebble:
hostname: moxacmepebble.mox1.example
domainname: mox1.example
image: mox_quickstart_moxmail
environment:
MOX_UID: "${MOX_UID}"
command: ["sh", "-c", "/quickstart/moxacmepebble.sh"]
volumes:
- ./testdata/quickstart/resolv.conf:/etc/resolv.conf
- ./testdata/quickstart:/quickstart
healthcheck:
test: netstat -nlt | grep ':25 '
interval: 1s
timeout: 1s
retries: 10
depends_on:
dns:
condition: service_healthy
acmepebble:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.10
# Second mox instance, with TLS cert/keys from files.
moxmail2:
hostname: moxmail2.mox2.example
domainname: mox2.example
image: mox_quickstart_moxmail
environment:
MOX_UID: "${MOX_UID}"
command: ["sh", "-c", "/quickstart/moxmail2.sh"]
volumes:
- ./testdata/quickstart/resolv.conf:/etc/resolv.conf
- ./testdata/quickstart:/quickstart
healthcheck:
test: netstat -nlt | grep ':25 '
interval: 1s
timeout: 1s
retries: 10
depends_on:
dns:
condition: service_healthy
acmepebble:
condition: service_healthy
# moxacmepebble creates tmp-pebble-ca.pem, needed by moxmail2 to trust the certificates offered by moxacmepebble.
moxacmepebble:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.20
dns:
hostname: dns.example
build:
dockerfile: Dockerfile.dns
# todo: figure out how to build from dockerfile with empty context without creating empty dirs in file system.
context: testdata/quickstart
volumes:
- ./testdata/quickstart/resolv.conf:/etc/resolv.conf
- ./testdata/quickstart:/quickstart
# We start with a base example.zone, but moxacmepebble appends its records,
# followed by moxmail2. They restart unbound after appending records.
command: ["sh", "-c", "set -ex; ls -l /etc/resolv.conf; chmod o+r /etc/resolv.conf; install -m 640 -o unbound /quickstart/unbound.conf /etc/unbound/; chmod 755 /quickstart; chmod 644 /quickstart/*.zone; cp /quickstart/example.zone /quickstart/example-quickstart.zone; ls -ld /quickstart /quickstart/reverse.zone; unbound -d -p -v"]
healthcheck:
test: netstat -nlu | grep '172.28.1.30:53 '
interval: 1s
timeout: 1s
retries: 10
networks:
mailnet1:
ipv4_address: 172.28.1.30
# pebble is a small acme server useful for testing. It creates a new CA
# certificate each time it starts, so we go through some trouble to configure the
# certificate in moxacmepebble and moxmail2.
acmepebble:
hostname: acmepebble.example
image: docker.io/letsencrypt/pebble:v2.3.1@sha256:fc5a537bf8fbc7cc63aa24ec3142283aa9b6ba54529f86eb8ff31fbde7c5b258
volumes:
- ./testdata/quickstart/resolv.conf:/etc/resolv.conf
- ./testdata/quickstart:/quickstart
command: ["sh", "-c", "set -ex; mount; ls -l /etc/resolv.conf; chmod o+r /etc/resolv.conf; pebble -config /quickstart/pebble-config.json"]
ports:
- 14000:14000 # ACME port
- 15000:15000 # Management port
healthcheck:
test: netstat -nlt | grep ':14000 '
interval: 1s
timeout: 1s
retries: 10
depends_on:
dns:
condition: service_healthy
networks:
mailnet1:
ipv4_address: 172.28.1.40
networks:
mailnet1:
driver: bridge
ipam:
driver: default
config:
- subnet: "172.28.1.0/24"

View file

@ -1,11 +1,10 @@
//go:build integration
// Run this using docker-compose.yml, see Makefile.
package main
import (
"context"
"crypto/tls"
"fmt"
"net"
"os"
@ -20,57 +19,25 @@ import (
"github.com/mjl-/mox/mox-"
"github.com/mjl-/mox/sasl"
"github.com/mjl-/mox/smtpclient"
"github.com/mjl-/mox/store"
)
var ctxbg = context.Background()
func tcheck(t *testing.T, err error, errmsg string) {
if err != nil {
t.Helper()
t.Fatalf("%s: %s", errmsg, err)
}
}
// Submit a message to mox, which sends it to postfix, which forwards back to mox.
// We check if we receive the message.
func TestDeliver(t *testing.T) {
xlog := mlog.New("integration")
mlog.Logfmt = true
log := mlog.New("test")
// Remove state.
os.RemoveAll("testdata/integration/data")
os.MkdirAll("testdata/integration/data", 0750)
// Cleanup afterwards, these are owned by root, annoying to have around due to
// permission errors.
defer os.RemoveAll("testdata/integration/data")
// Load mox config.
mox.ConfigStaticPath = "testdata/integration/config/mox.conf"
if errs := mox.LoadConfig(ctxbg, true, false); len(errs) > 0 {
t.Fatalf("loading mox config: %v", errs)
}
// Create new accounts
createAccount := func(email, password string) {
t.Helper()
acc, _, err := store.OpenEmail(email)
tcheck(t, err, "open account")
err = acc.SetPassword(password)
tcheck(t, err, "setting password")
err = acc.Close()
tcheck(t, err, "closing account")
}
createAccount("moxtest1@mox1.example", "pass1234")
createAccount("moxtest2@mox2.example", "pass1234")
createAccount("moxtest3@mox3.example", "pass1234")
// Start mox.
const mtastsdbRefresher = false
const skipForkExec = true
err := start(mtastsdbRefresher, skipForkExec)
tcheck(t, err, "starting mox")
hostname, err := os.Hostname()
tcheck(t, err, "hostname")
ourHostname, err := dns.ParseDomain(hostname)
tcheck(t, err, "parse hostname")
// Single update from IMAP IDLE.
type idleResponse struct {
@ -78,30 +45,42 @@ func TestDeliver(t *testing.T) {
err error
}
testDeliver := func(checkTime bool, imapaddr, imapuser, imappass string, fn func()) {
// Deliver submits a message over submissions, and checks with imap idle if the
// message is received by the destination mail server.
deliver := func(checkTime bool, dialtls bool, imaphost, imapuser, imappassword string, send func()) {
t.Helper()
// Make IMAP connection, we'll wait for a delivery notification with IDLE.
imapconn, err := net.Dial("tcp", imapaddr)
tcheck(t, err, "dial imap server")
// Connect to IMAP, execute IDLE command, which will return on deliver message.
// TLS certificates work because the container has the CA certificates configured.
var imapconn net.Conn
var err error
if dialtls {
imapconn, err = tls.Dial("tcp", imaphost, nil)
} else {
imapconn, err = net.Dial("tcp", imaphost)
}
tcheck(t, err, "dial imap")
defer imapconn.Close()
client, err := imapclient.New(imapconn, false)
imapc, err := imapclient.New(imapconn, false)
tcheck(t, err, "new imapclient")
_, _, err = client.Login(imapuser, imappass)
tcheck(t, err, "imap client login")
_, _, err = client.Select("inbox")
_, _, err = imapc.Login(imapuser, imappassword)
tcheck(t, err, "imap login")
_, _, err = imapc.Select("Inbox")
tcheck(t, err, "imap select inbox")
err = client.Commandf("", "idle")
tcheck(t, err, "imap idle command")
err = imapc.Commandf("", "idle")
tcheck(t, err, "write imap idle command")
_, _, _, err = client.ReadContinuation()
_, _, _, err = imapc.ReadContinuation()
tcheck(t, err, "read imap continuation")
idle := make(chan idleResponse)
go func() {
for {
untagged, err := client.ReadUntagged()
untagged, err := imapc.ReadUntagged()
idle <- idleResponse{untagged, err}
if err != nil {
return
@ -109,12 +88,12 @@ func TestDeliver(t *testing.T) {
}
}()
defer func() {
err := client.Writelinef("done")
err := imapc.Writelinef("done")
tcheck(t, err, "aborting idle")
}()
t0 := time.Now()
fn()
send()
// Wait for notification of delivery.
select {
@ -127,13 +106,19 @@ func TestDeliver(t *testing.T) {
if d := time.Since(t0); checkTime && d < 1*time.Second {
t.Fatalf("delivery took %v, but should have taken at least 1 second, the first-time sender delay", d)
}
case <-time.After(5 * time.Second):
case <-time.After(30 * time.Second):
t.Fatalf("timeout after 5s waiting for IMAP IDLE notification of new message, should take about 1 second")
}
}
submit := func(smtphost, smtpport, mailfrom, password, rcptto string) {
conn, err := net.Dial("tcp", net.JoinHostPort(smtphost, smtpport))
submit := func(dialtls bool, mailfrom, password, desthost, rcptto string) {
var conn net.Conn
var err error
if dialtls {
conn, err = tls.Dial("tcp", desthost, nil)
} else {
conn, err = net.Dial("tcp", desthost)
}
tcheck(t, err, "dial submission")
defer conn.Close()
@ -145,7 +130,7 @@ This is the message.
`, mailfrom, rcptto)
msg = strings.ReplaceAll(msg, "\n", "\r\n")
auth := []sasl.Client{sasl.NewClientPlain(mailfrom, password)}
c, err := smtpclient.New(mox.Context, log, conn, smtpclient.TLSOpportunistic, mox.Conf.Static.HostnameDomain, dns.Domain{ASCII: smtphost}, auth)
c, err := smtpclient.New(mox.Context, xlog, conn, smtpclient.TLSSkip, ourHostname, dns.Domain{ASCII: desthost}, auth)
tcheck(t, err, "smtp hello")
err = c.Deliver(mox.Context, mailfrom, rcptto, int64(len(msg)), strings.NewReader(msg), false, false)
tcheck(t, err, "deliver with smtp")
@ -153,18 +138,42 @@ This is the message.
tcheck(t, err, "close smtpclient")
}
testDeliver(true, "moxmail1.mox1.example:143", "moxtest1@mox1.example", "pass1234", func() {
submit("moxmail1.mox1.example", "587", "moxtest1@mox1.example", "pass1234", "root@postfix.example")
})
testDeliver(true, "moxmail1.mox1.example:143", "moxtest3@mox3.example", "pass1234", func() {
submit("moxmail2.mox2.example", "587", "moxtest2@mox2.example", "pass1234", "moxtest3@mox3.example")
})
// Make sure moxacmepebble has a TLS certificate.
conn, err := tls.Dial("tcp", "moxacmepebble.mox1.example:465", nil)
tcheck(t, err, "dial submission")
defer conn.Close()
testDeliver(false, "localserve.mox1.example:1143", "mox@localhost", "moxmoxmox", func() {
submit("localserve.mox1.example", "1587", "mox@localhost", "moxmoxmox", "any@any.example")
xlog.Print("submitting email to moxacmepebble, waiting for imap notification at moxmail2")
t0 := time.Now()
deliver(true, true, "moxmail2.mox2.example:993", "moxtest2@mox2.example", "accountpass4321", func() {
submit(true, "moxtest1@mox1.example", "accountpass1234", "moxacmepebble.mox1.example:465", "moxtest2@mox2.example")
})
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
testDeliver(false, "localserve.mox1.example:1143", "mox@localhost", "moxmoxmox", func() {
xlog.Print("submitting email to moxmail2, waiting for imap notification at moxacmepebble")
t0 = time.Now()
deliver(true, true, "moxacmepebble.mox1.example:993", "moxtest1@mox1.example", "accountpass1234", func() {
submit(true, "moxtest2@mox2.example", "accountpass4321", "moxmail2.mox2.example:465", "moxtest1@mox1.example")
})
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
xlog.Print("submitting email to postfix, waiting for imap notification at moxacmepebble")
t0 = time.Now()
deliver(true, true, "moxacmepebble.mox1.example:993", "moxtest1@mox1.example", "accountpass1234", func() {
submit(true, "moxtest1@mox1.example", "accountpass1234", "moxacmepebble.mox1.example:465", "root@postfix.example")
})
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
xlog.Print("submitting email to localserve")
t0 = time.Now()
deliver(false, false, "localserve.mox1.example:1143", "mox@localhost", "moxmoxmox", func() {
submit(false, "mox@localhost", "moxmoxmox", "localserve.mox1.example:1587", "moxtest1@mox1.example")
})
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
xlog.Print("submitting email to localserve")
t0 = time.Now()
deliver(false, false, "localserve.mox1.example:1143", "mox@localhost", "moxmoxmox", func() {
cmd := exec.Command("go", "run", ".", "sendmail", "mox@localhost")
const msg = `Subject: test
@ -174,7 +183,9 @@ a message.
var out strings.Builder
cmd.Stdout = &out
err := cmd.Run()
log.Print("sendmail", mlog.Field("output", out.String()))
xlog.Print("sendmail", mlog.Field("output", out.String()))
tcheck(t, err, "sendmail")
})
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
}

View file

@ -1,145 +0,0 @@
//go:build quickstart
// Run this using docker-compose.yml, see Makefile.
package main
import (
"context"
"crypto/tls"
"fmt"
"os"
"strings"
"testing"
"time"
"github.com/mjl-/mox/dns"
"github.com/mjl-/mox/imapclient"
"github.com/mjl-/mox/mlog"
"github.com/mjl-/mox/mox-"
"github.com/mjl-/mox/sasl"
"github.com/mjl-/mox/smtpclient"
)
var ctxbg = context.Background()
func tcheck(t *testing.T, err error, errmsg string) {
if err != nil {
t.Fatalf("%s: %s", errmsg, err)
}
}
func TestDeliver(t *testing.T) {
xlog := mlog.New("quickstart")
mlog.Logfmt = true
hostname, err := os.Hostname()
tcheck(t, err, "hostname")
ourHostname, err := dns.ParseDomain(hostname)
tcheck(t, err, "parse hostname")
// Deliver submits a message over submissions, and checks with imap idle if the
// message is received by the destination mail server.
deliver := func(desthost, mailfrom, password, rcptto, imaphost, imapuser, imappassword string) {
t.Helper()
// Connect to IMAP, execute IDLE command, which will return on deliver message.
// TLS certificates work because the container has the CA certificates configured.
imapconn, err := tls.Dial("tcp", imaphost+":993", nil)
tcheck(t, err, "dial imap")
defer imapconn.Close()
imaperr := make(chan error, 1)
go func() {
go func() {
x := recover()
if x == nil {
return
}
imaperr <- x.(error)
}()
xcheck := func(err error, format string) {
if err != nil {
panic(fmt.Errorf("%s: %w", format, err))
}
}
imapc, err := imapclient.New(imapconn, false)
xcheck(err, "new imapclient")
_, _, err = imapc.Login(imapuser, imappassword)
xcheck(err, "imap login")
_, _, err = imapc.Select("Inbox")
xcheck(err, "imap select inbox")
err = imapc.Commandf("", "idle")
xcheck(err, "write imap idle command")
_, _, _, err = imapc.ReadContinuation()
xcheck(err, "read imap continuation")
done := make(chan error)
go func() {
defer func() {
x := recover()
if x != nil {
done <- fmt.Errorf("%v", x)
}
}()
untagged, err := imapc.ReadUntagged()
if err != nil {
done <- err
return
}
if _, ok := untagged.(imapclient.UntaggedExists); !ok {
done <- fmt.Errorf("expected imapclient.UntaggedExists, got %#v", untagged)
return
}
done <- nil
}()
period := 30 * time.Second
timer := time.NewTimer(period)
defer timer.Stop()
select {
case err = <-done:
case <-timer.C:
err = fmt.Errorf("nothing within %v", period)
}
xcheck(err, "waiting for imap untagged response to idle")
imaperr <- nil
}()
conn, err := tls.Dial("tcp", desthost+":465", nil)
tcheck(t, err, "dial submission")
defer conn.Close()
msg := fmt.Sprintf(`From: <%s>
To: <%s>
Subject: test message
This is the message.
`, mailfrom, rcptto)
msg = strings.ReplaceAll(msg, "\n", "\r\n")
auth := []sasl.Client{sasl.NewClientPlain(mailfrom, password)}
c, err := smtpclient.New(mox.Context, xlog, conn, smtpclient.TLSSkip, ourHostname, dns.Domain{ASCII: desthost}, auth)
tcheck(t, err, "smtp hello")
err = c.Deliver(mox.Context, mailfrom, rcptto, int64(len(msg)), strings.NewReader(msg), false, false)
tcheck(t, err, "deliver with smtp")
err = c.Close()
tcheck(t, err, "close smtpclient")
err = <-imaperr
tcheck(t, err, "imap idle")
}
xlog.Print("submitting email to moxacmepebble, waiting for imap notification at moxmail2")
t0 := time.Now()
deliver("moxacmepebble.mox1.example", "moxtest1@mox1.example", "accountpass1234", "moxtest2@mox2.example", "moxmail2.mox2.example", "moxtest2@mox2.example", "accountpass4321")
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
xlog.Print("submitting email to moxmail2, waiting for imap notification at moxacmepebble")
t0 = time.Now()
deliver("moxmail2.mox2.example", "moxtest2@mox2.example", "accountpass4321", "moxtest1@mox1.example", "moxacmepebble.mox1.example", "moxtest1@mox1.example", "accountpass1234")
xlog.Print("success", mlog.Field("duration", time.Since(t0)))
}

View file

@ -1,4 +0,0 @@
FROM golang:1-alpine AS build
WORKDIR /mox
RUN apk add make bind-tools bash
env GOPROXY=off

View file

@ -1,83 +0,0 @@
Domains:
mox1.example:
LocalpartCaseSensitive: false
LocalpartCatchallSeparator: +
mox2.example:
LocalpartCaseSensitive: false
LocalpartCatchallSeparator: +
DKIM:
Selectors:
mox2dkim0:
Hash: sha256
DontSealHeaders: false
Headers:
- From
- To
- Subject
PrivateKeyFile: ../dkim/mox2dkim0-key.pem
Sign:
- mox2dkim0
# todo: DMARC:
# todo: MTASTS:
# todo: TLSRPT:
mox3.example:
LocalpartCaseSensitive: false
LocalpartCatchallSeparator: +
DKIM:
Selectors:
mox3dkim0:
Hash: sha256
DontSealHeaders: false
Headers:
- From
- To
- Subject
PrivateKeyFile: ../dkim/mox3dkim0-key.pem
Sign:
- mox3dkim0
Accounts:
moxtest1:
Domain: mox1.example
Destinations:
moxtest1@mox1.example: nil
JunkFilter:
Threshold: 0.9999
Params:
Onegrams: true
Twograms: true
Threegrams: false
MaxPower: .01
TopWords: 10
IgnoreWords: .1
RareWords: 1
moxtest2:
Domain: mox2.example
Destinations:
moxtest2@mox2.example: nil
JunkFilter:
Threshold: 0.9999
Params:
Onegrams: true
Twograms: true
Threegrams: false
MaxPower: .01
TopWords: 10
IgnoreWords: .1
RareWords: 1
moxtest3:
Domain: mox3.example
Destinations:
moxtest3@mox3.example: nil
SubjectPass:
Period: 1h
RejectsMailbox: rejects
JunkFilter:
Threshold: 0.9999
Params:
Onegrams: true
Twograms: true
Threegrams: false
MaxPower: .01
TopWords: 10
IgnoreWords: .1
RareWords: 1

View file

@ -1,73 +0,0 @@
DataDir: ../data
LogLevel: trace
Hostname: moxmail1.mox1.example
# only for integration test, where fork & exec is skipped
User: 0
TLS:
CA:
CertFiles:
- ../tls/ca.pem
Listeners:
mox1:
IPs:
- 172.28.1.10
Hostname: moxmail1.mox1.example
SMTP:
Enabled: true
NoSTARTTLS: true
FirstTimeSenderDelay: 1s
Submission:
Enabled: true
NoRequireSTARTTLS: true
IMAP:
Enabled: true
NoRequireSTARTTLS: true
mox2:
IPs:
- 172.28.2.10
Hostname: moxmail2.mox2.example
TLS:
KeyCerts:
-
CertFile: ../tls/moxmail2.pem
KeyFile: ../tls/moxmail2-key.pem
SMTP:
Enabled: true
Submission:
Enabled: true
NoRequireSTARTTLS: true
Submissions:
Enabled: true
IMAP:
Enabled: true
IMAPS:
Enabled: true
AdminHTTP:
Enabled: true
AdminHTTPS:
Enabled: true
MetricsHTTP:
Enabled: true
AutoconfigHTTPS:
Enabled: true
MTASTSHTTPS:
Enabled: true
mox3:
IPs:
- 172.28.3.10
Hostname: moxmail3.mox3.example
TLS:
KeyCerts:
-
CertFile: ../tls/moxmail3.pem
KeyFile: ../tls/moxmail3-key.pem
SMTP:
Enabled: true
FirstTimeSenderDelay: 1s
Submission:
Enabled: true
NoRequireSTARTTLS: true
Postmaster:
Account: moxtest1
Mailbox: postmaster

View file

@ -1,5 +0,0 @@
-----BEGIN PRIVATE KEY-----
Note: ed25519 private key for use with DKIM, generated by mox
MC4CAQAwBQYDK2VwBCIEIAVskzmutHg8DvS8jaxYMHuoV1z9tNZmSC8+iI84WlTm
-----END PRIVATE KEY-----

View file

@ -1,5 +0,0 @@
-----BEGIN PRIVATE KEY-----
Note: ed25519 private key for use with DKIM, generated by mox
MC4CAQAwBQYDK2VwBCIEINAds0VrnXkd/cUnAT4eQDKQoViHC1q6dBPEqG8SJxnz
-----END PRIVATE KEY-----

View file

@ -1,5 +0,0 @@
-----BEGIN PRIVATE KEY-----
Note: ed25519 private key for use with DKIM, generated by mox
MC4CAQAwBQYDK2VwBCIEIPXYWvzg39zC8pkPzYZbTKCAk4TjIICZzaklMrOyADW+
-----END PRIVATE KEY-----

View file

@ -5,29 +5,14 @@ $TTL 5m
@ NS dns.example.
moxmail1.mox1 IN A 172.28.1.10
moxmail2.mox2 IN A 172.28.2.10
moxmail3.mox3 IN A 172.28.3.10
postfixmail.postfix IN A 172.28.1.20
moxacmepebble.mox1 IN A 172.28.1.10
moxmail2.mox2 IN A 172.28.1.20
dns IN A 172.28.1.30
localserve.mox1 IN A 172.28.1.50
acmepebble IN A 172.28.1.40
test IN A 172.28.1.50
localserve.mox1 IN A 172.28.1.60
postfixmail.postfix IN A 172.28.1.70
mox1 MX 10 moxmail1.mox1.example.
mox2 MX 10 moxmail2.mox2.example.
mox3 MX 10 moxmail3.mox3.example.
postfix MX 10 postfixmail.postfix.example.
mox1dkim0._domainkey.mox1 IN TXT "v=DKIM1;h=sha256;t=s;k=ed25519;p=nNs/2BSurEunCKJjfE61p0r2C4OMv/S8IDU/p7nL91c="
mox2dkim0._domainkey.mox2 IN TXT "v=DKIM1;h=sha256;t=s;k=ed25519;p=gVAOjqEeNS2e6jjGX1c61zhCOPXMcX6o5If/AVI5STk="
mox3dkim0._domainkey.mox3 IN TXT "v=DKIM1;h=sha256;t=s;k=ed25519;p=vzv50BpMhk6moYWq9jBNR+oHmlZcL2LARgL9144nJfk="
postfixdkim0._domainkey.postfix IN TXT "v=DKIM1;h=sha256;t=s;k=ed25519;p=a4IsBTuMsSQjU+xVyx8KEd8eObis4FrCiV72OaEkvDY="
mox1 IN TXT "v=spf1 ip4:172.28.1.10 ip4:172.28.1.20 -all"
mox2 IN TXT "v=spf1 ip4:172.28.2.10 ip4:172.28.3.10 -all" ; 172.28.3.10 because that's where connections from mox to mox3 are going from. perhaps linux prefers to use same source ip if possible?
mox3 IN TXT "v=spf1 ip4:172.28.3.10 -all"
postfix IN TXT "v=spf1 ip4:172.28.1.20 -all"
_dmarc.mox1 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@mox1.example"
_dmarc.mox2 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@mox2.example"
_dmarc.mox3 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@mox3.example"
; _dmarc.mox4 IN TXT "v=DMARC1; p=reject; rua=mailto:dmarc-reports@postfix.example"

View file

@ -16,13 +16,18 @@ TLS:
CA:
CertFiles:
# So certificates from moxmail2 are trusted, and pebble's certificate is trusted.
- /quickstart/tls/ca.pem
- /integration/tls/ca.pem
EOF
(cat /quickstart/example.zone; sed -n '/^;/,/IN CAA/p' output.txt) >/quickstart/example-quickstart.zone
(
cat /integration/example.zone;
sed -n '/^;/,/IN CAA/p' output.txt |
# allow sending from postfix for mox1.example.
sed 's/mox1.example. *IN TXT "v=spf1 mx ~all"/mox1.example. IN TXT "v=spf1 mx ip4:172.28.1.70 ~all"/'
) >/integration/example-integration.zone
unbound-control -s 172.28.1.30 reload # reload unbound with zone file changes
CURL_CA_BUNDLE=/quickstart/tls/ca.pem curl -o /quickstart/tmp-pebble-ca.pem https://acmepebble.example:15000/roots/0
CURL_CA_BUNDLE=/integration/tls/ca.pem curl -o /integration/tmp-pebble-ca.pem https://acmepebble.example:15000/roots/0
mox serve &
while true; do

View file

@ -9,20 +9,20 @@ mkdir /tmp/mox
cd /tmp/mox
mox quickstart moxtest2@mox2.example "$MOX_UID" > output.txt
sed -i -e '/- 172.28.1.20/d' -e 's/- 0.0.0.0/- 172.28.1.20/' -e '/- ::/d' -e 's,ACME: .*$,KeyCerts:\n\t\t\t\t-\n\t\t\t\t\tCertFile: /quickstart/tls/moxmail2.pem\n\t\t\t\t\tKeyFile: /quickstart/tls/moxmail2-key.pem\n\t\t\t\t-\n\t\t\t\t\tCertFile: /quickstart/tls/mox2-autoconfig.pem\n\t\t\t\t\tKeyFile: /quickstart/tls/mox2-autoconfig-key.pem\n\t\t\t\t-\n\t\t\t\t\tCertFile: /quickstart/tls/mox2-mtasts.pem\n\t\t\t\t\tKeyFile: /quickstart/tls/mox2-mtasts-key.pem\n,' -e 's/SMTP:$/SMTP:\n\t\t\tFirstTimeSenderDelay: 1s/' config/mox.conf
sed -i -e '/- 172.28.1.20/d' -e 's/- 0.0.0.0/- 172.28.1.20/' -e '/- ::/d' -e 's,ACME: .*$,KeyCerts:\n\t\t\t\t-\n\t\t\t\t\tCertFile: /integration/tls/moxmail2.pem\n\t\t\t\t\tKeyFile: /integration/tls/moxmail2-key.pem\n\t\t\t\t-\n\t\t\t\t\tCertFile: /integration/tls/mox2-autoconfig.pem\n\t\t\t\t\tKeyFile: /integration/tls/mox2-autoconfig-key.pem\n\t\t\t\t-\n\t\t\t\t\tCertFile: /integration/tls/mox2-mtasts.pem\n\t\t\t\t\tKeyFile: /integration/tls/mox2-mtasts-key.pem\n,' -e 's/SMTP:$/SMTP:\n\t\t\tFirstTimeSenderDelay: 1s/' config/mox.conf
cat <<EOF >>config/mox.conf
TLS:
CA:
CertFiles:
# CA of our own certificates.
- /quickstart/tls/ca.pem
- /integration/tls/ca.pem
# CA used by moxacmepebble.
- /quickstart/tmp-pebble-ca.pem
- /integration/tmp-pebble-ca.pem
EOF
# A fresh file was set up by moxacmepebble.
sed -n '/^;/,/IN CAA/p' output.txt >>/quickstart/example-quickstart.zone
sed -n '/^;/,/IN CAA/p' output.txt >>/integration/example-integration.zone
unbound-control -s 172.28.1.30 reload # reload unbound with zone file changes
mox serve &

View file

@ -2,8 +2,8 @@
"pebble": {
"listenAddress": "0.0.0.0:14000",
"managementListenAddress": "0.0.0.0:15000",
"certificate": "/quickstart/tls/acmepebble.pem",
"privateKey": "/quickstart/tls/acmepebble-key.pem",
"certificate": "/integration/tls/acmepebble.pem",
"privateKey": "/integration/tls/acmepebble-key.pem",
"httpPort": 80,
"tlsPort": 443,
"ocspResponderURL": "",

View file

@ -3,8 +3,10 @@ $TTL 5m
@ IN SOA dns.example. hostmaster.example. (1 0m 0m 0m 5m)
10.1 IN PTR moxmail1.mox1.example.
10.2 IN PTR moxmail2.mox2.example.
10.3 IN PTR moxmail3.mox3.example.
20.1 IN PTR postfixmail.postfix.example.
10.1 IN PTR moxacmepebble.mox1.example.
20.1 IN PTR moxmail2.mox2.example.
30.1 IN PTR dns.example.
40.1 IN PTR acmepebble.example.
50.1 IN PTR test.example.
60.1 IN PTR localserve.mox1.example.
70.1 IN PTR postfixmail.postfix.example.

View file

@ -1,6 +1,7 @@
default:
cfssl genkey -initca cfssl-ca-csr.json | cfssljson -bare ca
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname moxmail1.mox1.example - | cfssljson -bare moxmail1
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname moxmail2.mox2.example - | cfssljson -bare moxmail2
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname moxmail3.mox3.example - | cfssljson -bare moxmail3
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname autoconfig.mox2.example - | cfssljson -bare mox2-autoconfig
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname mta-sts.mox2.example - | cfssljson -bare mox2-mtasts
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname acmepebble.example - | cfssljson -bare acmepebble
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname postfixmail.postfix.example - | cfssljson -bare postfixmail

View file

@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIAIxWviXAT3jP2y0nbypyq+r9SoToR1Z8l4/ShXFalyPoAoGCCqGSM49
AwEHoUQDQgAEsW53/bewar4hugHCihjjl6ljDq21xPq96IJMMTjrGSyDQQczZEba
6FVLV/RN/oE59Tx1a3jEusyooKnIj6ut+Q==
MHcCAQEEIIGDc32mcAt+9t3WmJvmeCLZK9aDjD6CrLjOvZx4zlRzoAoGCCqGSM49
AwEHoUQDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3HjsP7zi
e6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3A==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +1,8 @@
-----BEGIN CERTIFICATE REQUEST-----
MIH0MIGaAgEAMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEsW53/bewar4hugHCihjjl6ljDq21xPq96IJMMTjrGSyDQQcz
ZEba6FVLV/RN/oE59Tx1a3jEusyooKnIj6ut+aAiMCAGCSqGSIb3DQEJDjETMBEw
DwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNJADBGAiEAtwFHGm+7zqxnpj6i
EwLMRlXOY0U23xQajcLA/IknZkQCIQCB5ynsMvFJ49EmkcrfRALSqHIHZneH9p0Q
1CHHfQj6Fg==
MIHzMIGaAgEAMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3Hjs
P7zie6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3KAiMCAGCSqGSIb3DQEJDjETMBEw
DwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAuAJlvbFItRqBOHMV
aqUz2HNGocVLeeBjY9yWvI//Mo0CIC3Lzbh32xwaBwASggudm1OVAhDcvfzVJE68
+INvsUeP
-----END CERTIFICATE REQUEST-----

View file

@ -1,10 +1,10 @@
-----BEGIN CERTIFICATE-----
MIIBcjCCARigAwIBAgIUZhjg/4oAiX7YspAARmOjFojGseQwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTgzNzAwWhgPMjA1MzA1
MjcxODM3MDBaMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEsW53/bewar4hugHCihjjl6ljDq21xPq96IJMMTjrGSyDQQcz
ZEba6FVLV/RN/oE59Tx1a3jEusyooKnIj6ut+aNCMEAwDgYDVR0PAQH/BAQDAgEG
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFO2GIS1aM4NtFS+a+DrMcmjWiKYB
MAoGCCqGSM49BAMCA0gAMEUCIQCvkuuvPMAW1d3Xns7TYjSa/NFxSjFyiGKsaaJX
ohvCLgIgUkSVYc71RHa5AB3geVbXmmwrFF40+gB1cW7oGwkScBM=
MIIBcjCCARigAwIBAgIUE8iskCUxfwqpv6F+nsXp7D4uqeYwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1
MjcxNTM1MDBaMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3Hjs
P7zie6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3KNCMEAwDgYDVR0PAQH/BAQDAgEG
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKUFNkPBlmKeQdvgjR0ORFnDmuTt
MAoGCCqGSM49BAMCA0gAMEUCIQCpOIZyFiHyAYZyjzj7HQSAsCeXzV/XuUXCJ+hR
R7uB4QIgUd6M84/3KdbdO7JW5W8saBh0hZ+kMhfQj5NEXy0VUtU=
-----END CERTIFICATE-----

View file

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOZXlR9z/jixe9bjSjHOURN0EFLTr9Wumw7W3Zr+XMPmoAoGCCqGSM49
AwEHoUQDQgAEjzxO852bzPodARDVgWUk+/Xy+G4SEImtN/5De0KgcUWXvVuJFjGg
ruBgyBAoHEkYau53Jcu3ZjHRFdi9RkwlbA==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHuMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASPPE7znZvM+h0B
ENWBZST79fL4bhIQia03/kN7QqBxRZe9W4kWMaCu4GDIECgcSRhq7ncly7dmMdEV
2L1GTCVsoDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMS5t
b3gxLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAKng26zqtKmRJtpkIdJNQD4C
hIBp+0jUC6apWFW8bvdFAiA/l0HfqQ1/OApMdgM8gNxZSwl13ZCqJlacTwYfkm4r
1Q==
-----END CERTIFICATE REQUEST-----

View file

@ -1,12 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBtjCCAVygAwIBAgIUeowpo7RMCenGjlCR+4SEza90HVIwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTgzNzAwWhgPMjA1MzA1
MjcxODM3MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASPPE7znZvM+h0B
ENWBZST79fL4bhIQia03/kN7QqBxRZe9W4kWMaCu4GDIECgcSRhq7ncly7dmMdEV
2L1GTCVso4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBReQyt9RscC4SFTh6RPr1uxYSUWjDAf
BgNVHSMEGDAWgBTthiEtWjODbRUvmvg6zHJo1oimATAjBgNVHREBAf8EGTAXghVt
b3htYWlsMS5tb3gxLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIgC2+MAUGSugMc
ffJ698+eTVHlxpR8C9PCs8udQVv2noYCIQC4ubNYPW3ZYdvQlRf2Svf3Al2vRl1N
pqt76JJVh9NTMA==
-----END CERTIFICATE-----

View file

@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIOw1oRBmOXVQd5MZiN1LzPqvqyoCoUpOc3GhO60WRgKFoAoGCCqGSM49
AwEHoUQDQgAEraCc8aRtk7kusBZ1FK/DMPiicc9FEjvbtHWT8lCPMAXjKWU/wG31
OktPDzfzu3Unvw1HT+/ljUahJ94InlSDZQ==
MHcCAQEEICvD+j+bji24hVIcRFrWPbQd6sXKmAuMtFUq175VY6K7oAoGCCqGSM49
AwEHoUQDQgAEZS5yh9kP/DgN94O+4hcNsyBt+CgQc8wZAE96GEhrNk+bgqwWpfTV
3ZiKfMKCvCqj+yKzwSi/3YyMAymghBMdng==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +1,8 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHuMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAStoJzxpG2TuS6w
FnUUr8Mw+KJxz0USO9u0dZPyUI8wBeMpZT/AbfU6S08PN/O7dSe/DUdP7+WNRqEn
3gieVINloDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMi5t
b3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIgbFop/kVfFLIWtKVZEvy2YSJU
6zheYeteOTvIuwgcK+UCIQCOXHT/WxsqCUorpT08WHAvfaIgKCOz0PLTL7MtdJED
rQ==
MIHuMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARlLnKH2Q/8OA33
g77iFw2zIG34KBBzzBkAT3oYSGs2T5uCrBal9NXdmIp8woK8KqP7IrPBKL/djIwD
KaCEEx2eoDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMi5t
b3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAP6qbRb8RikC8x5cmUix0+yO
UjFMytNaZtGMKAvGceSbAiAZ8neHjd04tJEI7Y3a5TDXtwz4D66K5CGdnMC7MRam
5w==
-----END CERTIFICATE REQUEST-----

View file

@ -1,12 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIBtTCCAVygAwIBAgIUc136y8tcpMqkiAC9g4isvHRFrgMwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTgzNzAwWhgPMjA1MzA1
MjcxODM3MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAStoJzxpG2TuS6w
FnUUr8Mw+KJxz0USO9u0dZPyUI8wBeMpZT/AbfU6S08PN/O7dSe/DUdP7+WNRqEn
3gieVINlo4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBS8ILNAqiWwz+hdmGG5gJ29JZKgdDAf
BgNVHSMEGDAWgBTthiEtWjODbRUvmvg6zHJo1oimATAjBgNVHREBAf8EGTAXghVt
b3htYWlsMi5tb3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDRwAwRAIgSCdO0boA280B
fOGKeWl8+TAA/Lx7HJSza0fmO33ndWgCIGyw+LOgYchONeCGfG0YLz5y2v2J5hme
31FhVsoqAcq4
MIIBtjCCAVygAwIBAgIUaowxow/mwlT7vGZQclZFCrJFTEIwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1
MjcxNTM1MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARlLnKH2Q/8OA33
g77iFw2zIG34KBBzzBkAT3oYSGs2T5uCrBal9NXdmIp8woK8KqP7IrPBKL/djIwD
KaCEEx2eo4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTD3lkc5vvR1/6nkYxgmKgYA33YNjAf
BgNVHSMEGDAWgBSlBTZDwZZinkHb4I0dDkRZw5rk7TAjBgNVHREBAf8EGTAXghVt
b3htYWlsMi5tb3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAMBmK6kEflN6
8U/Y5EbhpCn7X3uV5Fbh59IHFJm8uK7XAiBQ0VVzueEO70TCAiGLllnpqrZq86Fa
XWoHOzoczCmZBw==
-----END CERTIFICATE-----

View file

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIEO5gTEH/gvyLz3Gjck5bjeno8Lt7agmk15u2Jv0Pd1xoAoGCCqGSM49
AwEHoUQDQgAEI1hS7Pkx6LJwkTGQ2pPME3J4F1IsyuWM9rrFzWoziBxof4rhqxhU
EkDjDMqJSEj+f/0W6IUSmkou1khyAOu7Og==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHvMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQjWFLs+THosnCR
MZDak8wTcngXUizK5Yz2usXNajOIHGh/iuGrGFQSQOMMyolISP5//RbohRKaSi7W
SHIA67s6oDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMy5t
b3gzLmV4YW1wbGUwCgYIKoZIzj0EAwIDSQAwRgIhALYlavlUXSDyql3djjXmkivJ
vP2o6/UYvycCD5Zs41LyAiEA5Dl/BUou/9mdQZ1wtO7dECV2og3LFqbux9HH5hhq
CHQ=
-----END CERTIFICATE REQUEST-----

View file

@ -1,12 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBtzCCAVygAwIBAgIUYsOfXT2yt+VXzQdYJZ6xDrpduyUwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTgzNzAwWhgPMjA1MzA1
MjcxODM3MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQjWFLs+THosnCR
MZDak8wTcngXUizK5Yz2usXNajOIHGh/iuGrGFQSQOMMyolISP5//RbohRKaSi7W
SHIA67s6o4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTgWT5PO/9Hs25S2/AEIh8Kbt2Y+DAf
BgNVHSMEGDAWgBTthiEtWjODbRUvmvg6zHJo1oimATAjBgNVHREBAf8EGTAXghVt
b3htYWlsMy5tb3gzLmV4YW1wbGUwCgYIKoZIzj0EAwIDSQAwRgIhAN4LwY0/jkr7
Q9kCV2EeTgvja2XKu6kwdptBGacRRezdAiEAtmjbVuUk6OgF40a2IgJD1tbRRF55
M4T7VRdZJTdIDHQ=
-----END CERTIFICATE-----

View file

@ -1,5 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIJo/6dn+2V2ffJgRScOIX6waHFPNUaDOCR05BW0vHeDsoAoGCCqGSM49
AwEHoUQDQgAEw4QmYTaA5csyzcmJ2V/40xGkJ7woQxxmIyU5OzpYRCz4ejcVQPrg
4/3LS3Tr1SoUJXr/a8NoduQDOX/KvkAadg==
MHcCAQEEIDZojp22U22aP2yhoReSgYeVdFgQMXjoOjPAkvGZ7D2UoAoGCCqGSM49
AwEHoUQDQgAEW6LWFaeb6BBYsUMA13PUe/9JSre4qSgJQNLkRAlHUoyopTwjlDZw
PbnRqqYMt7Y+DJlj+OVtImExXSufvo66yQ==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +1,8 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHzMIGbAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATDhCZhNoDlyzLN
yYnZX/jTEaQnvChDHGYjJTk7OlhELPh6NxVA+uDj/ctLdOvVKhQlev9rw2h25AM5
f8q+QBp2oDkwNwYJKoZIhvcNAQkOMSowKDAmBgNVHREEHzAdghtwb3N0Zml4bWFp
bC5wb3N0Zml4LmV4YW1wbGUwCgYIKoZIzj0EAwIDRwAwRAIgEHqFqWnzkb+AuQSy
g5WbGDmWV0PC3cn3ZrhnKph+JRYCICHIOwP30IrU2vZlRw7hSJfF73Kp97bZnKnx
hKFU2mu2
MIH0MIGbAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARbotYVp5voEFix
QwDXc9R7/0lKt7ipKAlA0uRECUdSjKilPCOUNnA9udGqpgy3tj4MmWP45W0iYTFd
K5++jrrJoDkwNwYJKoZIhvcNAQkOMSowKDAmBgNVHREEHzAdghtwb3N0Zml4bWFp
bC5wb3N0Zml4LmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhANTF3PngKdGDEPpm
G2SmWmtY/rfVfK5tIJyOZF6c5Yt7AiBZYYgP2YkM/4U1n3z4pPJLI9HFkELIlgU+
H9tLemIc/Q==
-----END CERTIFICATE REQUEST-----

View file

@ -1,12 +1,12 @@
-----BEGIN CERTIFICATE-----
MIIBvDCCAWKgAwIBAgIUenc5veQllvPUqrUPTtB8eFtJvHkwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTgzNzAwWhgPMjA1MzA1
MjcxODM3MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATDhCZhNoDlyzLN
yYnZX/jTEaQnvChDHGYjJTk7OlhELPh6NxVA+uDj/ctLdOvVKhQlev9rw2h25AM5
f8q+QBp2o4GhMIGeMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRvX8dsWXBuohuUI6tMLaGRKG6j6jAf
BgNVHSMEGDAWgBTthiEtWjODbRUvmvg6zHJo1oimATApBgNVHREBAf8EHzAdghtw
b3N0Zml4bWFpbC5wb3N0Zml4LmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIgdqqP
rKV8yZ+XjDDzj9qp9VNZRqDRfVfYJoMY7c0qx1ECIQCMVEKWwyR0s7dsy7CAibBm
oaIOieBYkklXb1cnraoZsg==
MIIBvDCCAWKgAwIBAgIUC0PorNW2+71N4VeYmYlbKt66Jg8wCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNzIzMjAwNzAwWhgPMjA1MzA3
MTUyMDA3MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARbotYVp5voEFix
QwDXc9R7/0lKt7ipKAlA0uRECUdSjKilPCOUNnA9udGqpgy3tj4MmWP45W0iYTFd
K5++jrrJo4GhMIGeMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRb1GaGZrZmbnOli4xUMg9mfkxgUDAf
BgNVHSMEGDAWgBSlBTZDwZZinkHb4I0dDkRZw5rk7TApBgNVHREBAf8EHzAdghtw
b3N0Zml4bWFpbC5wb3N0Zml4LmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAIzx
DFc5uy7d8qviR2HrjHA9XLviW2PwaGQJrNAalNmuAiB2CEaJ7RJL37bWddCi4L1T
JZLoZIrbKuAb5nd7/GTcNw==
-----END CERTIFICATE-----

View file

@ -1,15 +1,19 @@
server:
interface: 172.28.1.30
access-control: 0.0.0.0/0 allow
logfile: /dev/stdout
use-syslog: no
logfile: ""
domain-insecure: "example"
local-zone: "28.172.in-addr.arpa." nodefault
remote-control:
control-enable: yes
control-interface: 0.0.0.0
control-use-cert: no
auth-zone:
name: "example"
zonefile: "/etc/unbound/example.zone"
zonefile: "/integration/example-integration.zone"
auth-zone:
name: "28.172.in-addr.arpa"
zonefile: "/etc/unbound/reverse.zone"
zonefile: "/integration/reverse.zone"

View file

@ -1,2 +0,0 @@
FROM alpine:3.17
RUN apk add unbound bind-tools mailx

View file

@ -1,12 +0,0 @@
$ORIGIN example.
$TTL 5m
@ IN SOA dns.example. webmaster.example. (1 0m 0m 0m 5m)
@ NS dns.example.
moxacmepebble.mox1 IN A 172.28.1.10
moxmail2.mox2 IN A 172.28.1.20
dns IN A 172.28.1.30
acmepebble IN A 172.28.1.40
test IN A 172.28.1.50

View file

@ -1 +0,0 @@
nameserver 172.28.1.30

View file

@ -1,10 +0,0 @@
$ORIGIN 28.172.in-addr.arpa.
$TTL 5m
@ IN SOA dns.example. hostmaster.example. (1 0m 0m 0m 5m)
10.1 IN PTR moxacmepebble.mox1.example.
20.1 IN PTR moxmail2.mox2.example.
30.1 IN PTR dns.example.
40.1 IN PTR acmepebble.example.
50.1 IN PTR test.example.

View file

@ -1,6 +0,0 @@
default:
cfssl genkey -initca cfssl-ca-csr.json | cfssljson -bare ca
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname moxmail2.mox2.example - | cfssljson -bare moxmail2
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname autoconfig.mox2.example - | cfssljson -bare mox2-autoconfig
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname mta-sts.mox2.example - | cfssljson -bare mox2-mtasts
echo '{}' | cfssl gencert -config config.json -profile server -ca ca.pem -ca-key ca-key.pem -hostname acmepebble.example - | cfssljson -bare acmepebble

View file

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIGDc32mcAt+9t3WmJvmeCLZK9aDjD6CrLjOvZx4zlRzoAoGCCqGSM49
AwEHoUQDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3HjsP7zi
e6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3A==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHzMIGaAgEAMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3Hjs
P7zie6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3KAiMCAGCSqGSIb3DQEJDjETMBEw
DwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAgNIADBFAiEAuAJlvbFItRqBOHMV
aqUz2HNGocVLeeBjY9yWvI//Mo0CIC3Lzbh32xwaBwASggudm1OVAhDcvfzVJE68
+INvsUeP
-----END CERTIFICATE REQUEST-----

View file

@ -1,10 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBcjCCARigAwIBAgIUE8iskCUxfwqpv6F+nsXp7D4uqeYwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1
MjcxNTM1MDBaMBYxFDASBgNVBAMTC21veCB0ZXN0IGNhMFkwEwYHKoZIzj0CAQYI
KoZIzj0DAQcDQgAEd8+vkLAmeuBQIhlimnnmltg9c1Pv3j2xpktYvHQqxAJd3Hjs
P7zie6jxWIyVmyqeiHcXE2exI9u8aE64TCZL3KNCMEAwDgYDVR0PAQH/BAQDAgEG
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKUFNkPBlmKeQdvgjR0ORFnDmuTt
MAoGCCqGSM49BAMCA0gAMEUCIQCpOIZyFiHyAYZyjzj7HQSAsCeXzV/XuUXCJ+hR
R7uB4QIgUd6M84/3KdbdO7JW5W8saBh0hZ+kMhfQj5NEXy0VUtU=
-----END CERTIFICATE-----

View file

@ -1,10 +0,0 @@
{
"CN": "mox test ca",
"key": {
"algo": "ecdsa",
"size": 256
},
"ca": {
"expiry": "262800h"
}
}

View file

@ -1,17 +0,0 @@
{
"signing": {
"default": {
"expiry": "262800h"
},
"profiles": {
"server": {
"expiry": "262800h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
}
}
}
}

View file

@ -1,5 +0,0 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEICvD+j+bji24hVIcRFrWPbQd6sXKmAuMtFUq175VY6K7oAoGCCqGSM49
AwEHoUQDQgAEZS5yh9kP/DgN94O+4hcNsyBt+CgQc8wZAE96GEhrNk+bgqwWpfTV
3ZiKfMKCvCqj+yKzwSi/3YyMAymghBMdng==
-----END EC PRIVATE KEY-----

View file

@ -1,8 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIHuMIGVAgEAMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARlLnKH2Q/8OA33
g77iFw2zIG34KBBzzBkAT3oYSGs2T5uCrBal9NXdmIp8woK8KqP7IrPBKL/djIwD
KaCEEx2eoDMwMQYJKoZIhvcNAQkOMSQwIjAgBgNVHREEGTAXghVtb3htYWlsMi5t
b3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAP6qbRb8RikC8x5cmUix0+yO
UjFMytNaZtGMKAvGceSbAiAZ8neHjd04tJEI7Y3a5TDXtwz4D66K5CGdnMC7MRam
5w==
-----END CERTIFICATE REQUEST-----

View file

@ -1,12 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIBtjCCAVygAwIBAgIUaowxow/mwlT7vGZQclZFCrJFTEIwCgYIKoZIzj0EAwIw
FjEUMBIGA1UEAxMLbW94IHRlc3QgY2EwIBcNMjMwNjA0MTUzNTAwWhgPMjA1MzA1
MjcxNTM1MDBaMAAwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARlLnKH2Q/8OA33
g77iFw2zIG34KBBzzBkAT3oYSGs2T5uCrBal9NXdmIp8woK8KqP7IrPBKL/djIwD
KaCEEx2eo4GbMIGYMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcD
ATAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTD3lkc5vvR1/6nkYxgmKgYA33YNjAf
BgNVHSMEGDAWgBSlBTZDwZZinkHb4I0dDkRZw5rk7TAjBgNVHREBAf8EGTAXghVt
b3htYWlsMi5tb3gyLmV4YW1wbGUwCgYIKoZIzj0EAwIDSAAwRQIhAMBmK6kEflN6
8U/Y5EbhpCn7X3uV5Fbh59IHFJm8uK7XAiBQ0VVzueEO70TCAiGLllnpqrZq86Fa
XWoHOzoczCmZBw==
-----END CERTIFICATE-----

View file

@ -1,2 +0,0 @@
For TLS, keys are generated using https://github.com/cloudflare/cfssl
These private keys are published online, don't use them for anything other than local testing.

View file

@ -1,19 +0,0 @@
server:
interface: 172.28.1.30
access-control: 0.0.0.0/0 allow
logfile: ""
domain-insecure: "example"
local-zone: "28.172.in-addr.arpa." nodefault
remote-control:
control-enable: yes
control-interface: 0.0.0.0
control-use-cert: no
auth-zone:
name: "example"
zonefile: "/quickstart/example-quickstart.zone"
auth-zone:
name: "28.172.in-addr.arpa"
zonefile: "/quickstart/reverse.zone"