local-infra: local, sandboxed atmosphere infra #684

closed
opened by boltless.me targeting master from sandboxed-atmosphere
+45
local-infra/Caddyfile
···
+
{
+
storage file_system /data/
+
debug
+
pki {
+
ca localtangled {
+
name "LocalTangledCA"
+
}
+
}
+
auto_https disable_redirects
+
}
+
+
plc.tngl.boltless.dev {
+
tls {
+
issuer internal {
+
ca localtangled
+
}
+
}
+
reverse_proxy http://plc:8080
+
}
+
+
*.pds.tngl.boltless.dev, pds.tngl.boltless.dev {
+
tls {
+
issuer internal {
+
ca localtangled
+
}
+
}
+
reverse_proxy http://pds:3000
+
}
+
+
jetstream.tngl.boltless.dev {
+
tls {
+
issuer internal {
+
ca localtangled
+
}
+
}
+
reverse_proxy http://jetstream:6008
+
}
+
+
http://knot.tngl.boltless.dev {
+
reverse_proxy http://host.docker.internal:6000
+
}
+
+
http://spindle.tngl.boltless.dev {
+
reverse_proxy http://host.docker.internal:6555
+
}
+12
local-infra/cert/localtangled/intermediate.crt
···
+
-----BEGIN CERTIFICATE-----
+
MIIBuTCCAWCgAwIBAgIRALKb0dndMd7jlCHAzm0G+N4wCgYIKoZIzj0EAwIwKTEn
+
MCUGA1UEAxMeTG9jYWxUYW5nbGVkQ0EgLSAyMDI1IEVDQyBSb290MB4XDTI1MTAy
+
MTA3NDAwNloXDTI1MTAyODA3NDAwNlowLDEqMCgGA1UEAxMhTG9jYWxUYW5nbGVk
+
Q0EgLSBFQ0MgSW50ZXJtZWRpYXRlMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE
+
bX+zyr9rLxF3E8oCZwJluCKX/xmU4waabkjaTGbI5K0cemiAAmZRJ2lVhgh+KfXD
+
PpTmt+YE6FUF4xAWADOUuaNmMGQwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQI
+
MAYBAf8CAQAwHQYDVR0OBBYEFIoGsfx3Qg/9qG7tm7CZ1pHYl3prMB8GA1UdIwQY
+
MBaAFCkl8dPP2IAMTPru6WEHLP1hySEQMAoGCCqGSM49BAMCA0cAMEQCIFc3gOEl
+
aUR/OWbQuWvYwoTZs81ERj73ZeQWy4a3i4ooAiAB7Mnih/7kEvLyfkjLRgRXrtlq
+
kVmXVyWHIncR6Bsktw==
+
-----END CERTIFICATE-----
+5
local-infra/cert/localtangled/intermediate.key
···
+
-----BEGIN EC PRIVATE KEY-----
+
MHcCAQEEIB1EH4KZGLcfO0neWDuV3oWMXPEze8JTsyKFoQuYApFSoAoGCCqGSM49
+
AwEHoUQDQgAEbX+zyr9rLxF3E8oCZwJluCKX/xmU4waabkjaTGbI5K0cemiAAmZR
+
J2lVhgh+KfXDPpTmt+YE6FUF4xAWADOUuQ==
+
-----END EC PRIVATE KEY-----
+11
local-infra/cert/localtangled/root.crt
···
+
-----BEGIN CERTIFICATE-----
+
MIIBlTCCATygAwIBAgIRAMDTcwNxYDMgtUNC5LkCeEQwCgYIKoZIzj0EAwIwKTEn
+
MCUGA1UEAxMeTG9jYWxUYW5nbGVkQ0EgLSAyMDI1IEVDQyBSb290MB4XDTI1MTAx
+
NzE2MTE0NVoXDTM1MDgyNjE2MTE0NVowKTEnMCUGA1UEAxMeTG9jYWxUYW5nbGVk
+
Q0EgLSAyMDI1IEVDQyBSb290MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE7rFM
+
4oNfT0UMqMuc3L60TCLeTd58WFSUYnKl7R1HOHDWeWZhhoNdWguXJSHhFPiWmQ5E
+
+fiI7KvDAVQGHzfUAqNFMEMwDgYDVR0PAQH/BAQDAgEGMBIGA1UdEwEB/wQIMAYB
+
Af8CAQEwHQYDVR0OBBYEFCkl8dPP2IAMTPru6WEHLP1hySEQMAoGCCqGSM49BAMC
+
A0cAMEQCIFjSGjvie1gO/JuNtP2HqeUHQNEh82K1fXdks54up3KEAiBWQDaOYeZ2
+
zVTiKe8ZQHpH3glXsIS0USsxeKaohMp0zA==
+
-----END CERTIFICATE-----
+5
local-infra/cert/localtangled/root.key
···
+
-----BEGIN EC PRIVATE KEY-----
+
MHcCAQEEIBqEj1iG3q+OLBgHjWQ3UkvKjq4sy5ej47syIYWn/Ql/oAoGCCqGSM49
+
AwEHoUQDQgAE7rFM4oNfT0UMqMuc3L60TCLeTd58WFSUYnKl7R1HOHDWeWZhhoNd
+
WguXJSHhFPiWmQ5E+fiI7KvDAVQGHzfUAg==
+
-----END EC PRIVATE KEY-----
+82
local-infra/docker-compose.yml
···
+
name: tangled-local-infra
+
services:
+
caddy:
+
container_name: caddy
+
image: caddy:2
+
depends_on:
+
- pds
+
restart: unless-stopped
+
cap_add:
+
- NET_ADMIN
+
ports:
+
- "80:80"
+
- "443:443"
+
- "443:443/udp"
+
volumes:
+
- ./Caddyfile:/etc/caddy/Caddyfile
+
- ./cert/localtangled:/data/pki/authorities/localtangled
+
- caddy_data:/data
+
- caddy_config:/config
+
+
plc:
+
image: ghcr.io/bluesky-social/did-method-plc:plc-f2ab7516bac5bc0f3f86842fa94e996bd1b3815b
+
# did-method-plc only provides linux/amd64
+
platform: linux/amd64
+
container_name: plc
+
restart: unless-stopped
+
depends_on:
+
- plc_db
+
environment:
+
DEBUG_MODE: 1
+
LOG_ENABLED: "true"
+
LOG_LEVEL: "debug"
+
LOG_DESTINATION: 1
+
DB_CREDS_JSON: &DB_CREDS_JSON '{"username":"pg","password":"password","host":"plc_db","port":5432}'
+
DB_MIGRATE_CREDS_JSON: *DB_CREDS_JSON
+
PLC_VERSION: 0.0.1
+
PORT: 8080
+
+
plc_db:
+
image: postgres:14.4-alpine
+
container_name: plc_db
+
environment:
+
- POSTGRES_USER=pg
+
- POSTGRES_PASSWORD=password
+
- PGPORT=5432
+
volumes:
+
- plc:/var/lib/postgresql/data
+
+
pds:
+
container_name: pds
+
image: ghcr.io/bluesky-social/pds:0.4
+
restart: unless-stopped
+
volumes:
+
- pds:/pds
+
env_file:
+
- ./pds.env
+
+
# I can change the knot-docker and spindle-docker images,
+
# which means I can inject the cert to those containers
+
#
+
# so define *.tngl.boltless.dev as extra_hosts & inject certs to those two containers
+
# extra_hosts:
+
# plc.tngl.boltless.dev:host.docker.internal
+
+
jetstream:
+
container_name: jetstream
+
image: ghcr.io/bluesky-social/jetstream:sha-0ab10bd
+
restart: unless-stopped
+
volumes:
+
- jetstream:/data
+
environment:
+
- JETSTREAM_DATA_DIR=/data
+
# livness check interval to restart when no events are received (default: 15sec)
+
- JETSTREAM_LIVENESS_TTL=300s
+
- JETSTREAM_WS_URL=ws://pds:3000/xrpc/com.atproto.sync.subscribeRepos
+
+
volumes:
+
caddy_config:
+
caddy_data:
+
plc:
+
pds:
+
jetstream:
+17
local-infra/pds.env
···
+
PDS_JWT_SECRET=8cae8bffcc73d9932819650791e4e89a
+
PDS_ADMIN_PASSWORD=d6a902588cd93bee1af83f924f60cfd3
+
PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=2e92e336a50a618458e1097d94a1db86ec3fd8829d7735020cbae80625c761d7
+
+
LOG_ENABLED=true
+
+
# PDS_BSKY_APP_VIEW_DID=did:web:api.bsky.app
+
# PDS_BSKY_APP_VIEW_URL=https://api.bsky.app
+
+
PDS_DATA_DIRECTORY=/pds
+
PDS_BLOBSTORE_DISK_LOCATION=/pds/blocks
+
+
PDS_DID_PLC_URL=http://plc:8080
+
PDS_HOSTNAME=pds.tngl.boltless.dev
+
+
# PDS_REPORT_SERVICE_DID=did:plc:ar7c4by46qjdydhdevvrndac
+
# PDS_REPORT_SERVICE_URL=https://mod.bsky.app
+9
local-infra/readme.md
···
+
run compose
+
```
+
docker compose up -d
+
```
+
+
trust the cert (macOS)
+
```
+
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain ./local-infra/cert/localtangled/root.crt
+
```
+63
local-infra/scripts/create-test-account.sh
···
+
#!/bin/bash
+
set -o errexit
+
set -o nounset
+
set -o pipefail
+
+
source "$(dirname "$0")/../pds.env"
+
+
# curl a URL and fail if the request fails.
+
function curl_cmd_get {
+
curl --fail --silent --show-error "$@"
+
}
+
+
# curl a URL and fail if the request fails.
+
function curl_cmd_post {
+
curl --fail --silent --show-error --request POST --header "Content-Type: application/json" "$@"
+
}
+
+
# curl a URL but do not fail if the request fails.
+
function curl_cmd_post_nofail {
+
curl --silent --show-error --request POST --header "Content-Type: application/json" "$@"
+
}
+
+
USERNAME="${1:-}"
+
+
if [[ "${USERNAME}" == "" ]]; then
+
read -p "Enter a username: " USERNAME
+
fi
+
+
if [[ "${USERNAME}" == "" ]]; then
+
echo "ERROR: missing USERNAME parameter." >/dev/stderr
+
echo "Usage: $0 ${SUBCOMMAND} <USERNAME>" >/dev/stderr
+
exit 1
+
fi
+
+
PASSWORD="password"
+
INVITE_CODE="$(curl_cmd_post \
+
--user "admin:${PDS_ADMIN_PASSWORD}" \
+
--data '{"useCount": 1}' \
+
"https://${PDS_HOSTNAME}/xrpc/com.atproto.server.createInviteCode" | jq --raw-output '.code'
+
)"
+
RESULT="$(curl_cmd_post_nofail \
+
--data "{\"email\":\"${USERNAME}@${PDS_HOSTNAME}\", \"handle\":\"${USERNAME}.${PDS_HOSTNAME}\", \"password\":\"${PASSWORD}\", \"inviteCode\":\"${INVITE_CODE}\"}" \
+
"https://${PDS_HOSTNAME}/xrpc/com.atproto.server.createAccount"
+
)"
+
+
DID="$(echo $RESULT | jq --raw-output '.did')"
+
if [[ "${DID}" != did:* ]]; then
+
ERR="$(echo ${RESULT} | jq --raw-output '.message')"
+
echo "ERROR: ${ERR}" >/dev/stderr
+
echo "Usage: $0 <EMAIL> <HANDLE>" >/dev/stderr
+
exit 1
+
fi
+
+
echo
+
echo "Account created successfully!"
+
echo "-----------------------------"
+
echo "Handle : ${USERNAME}.${PDS_HOSTNAME}"
+
echo "DID : ${DID}"
+
echo "Password : ${PASSWORD}"
+
echo "-----------------------------"
+
echo "This is a test account with an insecure password."
+
echo "Make sure it's only used for development."
+
echo
+5
nix/vm.nix
···
};
# This is fine because any and all ports that are forwarded to host are explicitly marked above, we don't need a separate guest firewall
networking.firewall.enable = false;
+
services.dnsmasq.enable = true;
+
services.dnsmasq.settings.address = "/tngl.boltless.dev/10.0.2.2";
+
security.pki.certificates = [
+
(builtins.readFile ../local-infra/cert/localtangled/root.crt)
+
];
time.timeZone = "Europe/London";
services.getty.autologinUser = "root";
environment.systemPackages = with pkgs; [curl vim git sqlite litecli];