Services instellen
Ik wilde eerst docker swarm gebruiken, maar eigenlijk heb ik dat helemaal niet nodig. Ik heb maar een paar services en ik hoef geen dubbele te hebben o.i.d. Daarom gebruik ik docker compose met restart: unless-stopped of restart: always. De wachtwoorden e.d. versleutel ik met ansible vault.
Ik wil op alle plekken postgres 14 gebruiken. Dus daar wilde ik de compose bestanden op aanpassen, maar dat werkt niet overal. Dus dat is nog niet gelukt.
Om het makkelijker te maken ga ik de ports verdelen over een bepaalde range. Bijvoorbeeld voor ejbca van 6000-6099, voor taiga 6100-6199 enz. Verder moeten voor taiga, gitea en gitlab ook het domein/IP-adres ingesteld worden.
Ik wou de compose bestanden aanpassen zodat ze versienummer gebruiken i.p.v. latest. Volgens mij had ik van alles de laatste versie gepakt, maar het werkte toch niet. Ik snap niet goed waarom.
EJBCA compose-bestand
networks:
access-bridge:
driver: bridge
application-bridge:
driver: bridge
services:
ejbca-database:
container_name: ejbca-database
image: "library/mariadb:latest"
networks:
- application-bridge
environment:
- MYSQL_DATABASE=ejbca
- MYSQL_USER=ejbca
- MYSQL_PASSWORD=/run/secrets/ejbca-mysql-password
- MYSQL_ROOT_PASSWORD=/run/secrets/ejbca-root-password
secrets:
- ejbca-mysql-password
- ejbca-root-password
volumes:
- ejbcadb:/var/lib/mysql:rw
restart: always
ejbca-node1:
hostname: ejbca-node1
container_name: ejbca
image: keyfactor/ejbca-ce:latest
depends_on:
- ejbca-database
networks:
- access-bridge
- application-bridge
environment:
- DATABASE_JDBC_URL=jdbc:mariadb://ejbca-database:3306/ejbca?characterEncoding=UTF-8
- LOG_LEVEL_APP=INFO
- LOG_LEVEL_SERVER=INFO
- TLS_SETUP_ENABLED=simple
- DATABASE_PASSWORD=/run/secrets/ejbca-mysql-password
secrets:
- ejbca-mysql-password
ports:
- "80:8080"
- "443:8443"
restart: always
volumes:
ejbcadb:
secrets:
ejbca-root-password:
file: ./ejbca-root-password.txt
ejbca-mysql-password:
file: ./ejbca-mysql-password.txt
Het is beter om meerdere EJBCA containers te maken: een root CA (certificate authority) en een sub CA/issuing CA. Als je de enterprise-editie gebruikt ook een VA (validation authority) en een RA (registration authority). Die gebruiken we niet dus we hebben maar twee containers nodig. Je kan een nieuwe root CA maken met:
bin/ejbca.sh ca init TestRoot "C=SE,O=PrimeKey,CN=TestRoot" soft foo123 2048 RSA 365 --policy 2.5.29.32.0 SHA256WithRSA
foo123 is dan het wachtwoord. Daarna kan je van je nieuwe sub CA een "issuing CA" maken met:
bin/ejbca.sh ca init CaSignedByExteral "CN=This CA is Signed by an external CA" soft foo123 secp256r1 ECDSA 365 null SHA256withECDSA --signedby External -externalcachain chain.pem
foo123 is weer het wachtwoord, je hebt hiervoor een pem-bestand van je root CA nodig. Daar krijg je een csr-bestand die je handmatig moet signen met je root CA. Daarna kun je issuing CA activeren met:
bin/ejbca.sh ca importcacert CaSignedByExteral subcacertificate.pem
Volgens Keyfactor moet je dan ook Certificate Transparancy instellen, maar dat is alleen voor enterprise, dus dat kan niet. Ik denk dat dit alleen hoeft als we het aan het open internet willen hangen.
Daarna moet je handmatig certificate profiles maken. Je kan de RA view openstellen voor iedereen met onderstaand commando, maar je kan het beter handmatig instellen:
# Beter niet gebruiken
bin/ejbca.sh roles addrolemember --caname "" --role "Super Administrator Role" --value "" --with PublicAccessAuthenticationToken:TRANSPORT_CONFIDENTIAL
Hierna moet je nog inlogcertificaten instellen zoals hier beschreven.
Als dit niet werkt heb ik ook nog de oude manier:
Je kan met de cli volgens mij wel het certificaat dat je moet importeren in de browser generen (met ejbca.sh ra addendentity) maar ik heb geen manier gevonden om het te exporteren uit de container. Dus dit moet dan maar handmatig zoals beschreven in dit artikel, misschien wel het algoritme veranderen van RSA 2048 naar iets moderners/moeilijkers. De cli is gelimiteerd, wat goed is voor nocode configuraties, dus het is waarschijnlijk beter en makkelijker om het hele ca's maken, certificaten tekenen enz. met de hand te doen. Dus ook een eigen root ca maken aan de hand van dit artikel en het signen zoals hieronder beschreven.
User guide op mincit.gov.co geeft een aantal stappen om een "External CA" te signen. Dit helpt, je moet het SUBCA certificate profile klonen en aanpassen zoals je wil, bijvoorbeeld validity instellen op 1y. In het end entity profile moet ruimte zijn voor een CN en een O, O moet je dus toevoegen. Daarna kun je het signen in RA View van EJBCA. Je moet de volledige PEM-chain downloaden van het gesignde certificaat. Je moet ook de PEM downloaden van de root CA. Die moet je gebruiken in het ipa-server-install command als /path/to/signed_certificate en /path/to/external_ca_certificate. Dit moeten de volledige/absolute paden zijn.
Taiga compose-bestand
Voor het opzetten van taiga clone je deze repo. Je heb eigenlijk alleen maar de taiga-gateway/taiga.conf, docker-compose.yml, docker-compose-inits.yml en .env bestanden nodig. taiga-launch.sh en taiga-manage.sh maken het wel makkelijker maar zijn eigenlijk gewoon aliassen voor docker compose en dan een command.
Nadat de services draaien, moet je nog een superuser maken. Dat kan met manage.py in de taiga-back container.
Het compose-bestand:
x-environment:
&default-back-environment
# These environment variables will be used by taiga-back and taiga-async.
# Database settings
POSTGRES_DB: "taiga"
POSTGRES_USER: "${POSTGRES_USER}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
POSTGRES_HOST: "taiga-db"
# Taiga settings
TAIGA_SECRET_KEY: "${SECRET_KEY}"
TAIGA_SITES_SCHEME: "${TAIGA_SCHEME}"
TAIGA_SITES_DOMAIN: "${TAIGA_DOMAIN}"
TAIGA_SUBPATH: "${SUBPATH}"
# Email settings.
EMAIL_BACKEND: "django.core.mail.backends.${EMAIL_BACKEND}.EmailBackend"
DEFAULT_FROM_EMAIL: "${EMAIL_DEFAULT_FROM}"
EMAIL_USE_TLS: "${EMAIL_USE_TLS}"
EMAIL_USE_SSL: "${EMAIL_USE_SSL}"
EMAIL_HOST: "${EMAIL_HOST}"
EMAIL_PORT: "${EMAIL_PORT}"
EMAIL_HOST_USER: "${EMAIL_HOST_USER}"
EMAIL_HOST_PASSWORD: "${EMAIL_HOST_PASSWORD}"
# Rabbitmq settings
RABBITMQ_USER: "${RABBITMQ_USER}"
RABBITMQ_PASS: "${RABBITMQ_PASS}"
# Telemetry settings
ENABLE_TELEMETRY: "${ENABLE_TELEMETRY}"
# ...your customizations go here
x-volumes:
&default-back-volumes
# These volumens will be used by taiga-back and taiga-async.
- taiga-static-data:/taiga-back/static
- taiga-media-data:/taiga-back/media
# - ./config.py:/taiga-back/settings/config.py
services:
taiga-db:
image: postgres:12.3
environment:
POSTGRES_DB: "taiga"
POSTGRES_USER: "${POSTGRES_USER}"
POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"]
interval: 2s
timeout: 15s
retries: 5
start_period: 3s
volumes:
- taiga-db-data:/var/lib/postgresql/data
networks:
- taiga
restart: unless-stopped
ports:
- "5432:5432"
taiga-back:
image: taigaio/taiga-back:latest
environment: *default-back-environment
volumes: *default-back-volumes
networks:
- taiga
depends_on:
taiga-db:
condition: service_healthy
taiga-events-rabbitmq:
condition: service_started
taiga-async-rabbitmq:
condition: service_started
restart: unless-stopped
taiga-async:
image: taigaio/taiga-back:latest
entrypoint: ["/taiga-back/docker/async_entrypoint.sh"]
environment: *default-back-environment
volumes: *default-back-volumes
networks:
- taiga
depends_on:
taiga-db:
condition: service_healthy
taiga-events-rabbitmq:
condition: service_started
taiga-async-rabbitmq:
condition: service_started
restart: unless-stopped
taiga-async-rabbitmq:
image: rabbitmq:3.8-management-alpine
environment:
RABBITMQ_ERLANG_COOKIE: "${RABBITMQ_ERLANG_COOKIE}"
RABBITMQ_DEFAULT_USER: "${RABBITMQ_USER}"
RABBITMQ_DEFAULT_PASS: "${RABBITMQ_PASS}"
RABBITMQ_DEFAULT_VHOST: "${RABBITMQ_VHOST}"
hostname: "taiga-async-rabbitmq"
volumes:
- taiga-async-rabbitmq-data:/var/lib/rabbitmq
networks:
- taiga
restart: unless-stopped
taiga-front:
image: taigaio/taiga-front:latest
environment:
TAIGA_URL: "${TAIGA_SCHEME}://${TAIGA_DOMAIN}"
TAIGA_WEBSOCKETS_URL: "${WEBSOCKETS_SCHEME}://${TAIGA_DOMAIN}"
TAIGA_SUBPATH: "${SUBPATH}"
# ...your customizations go here
networks:
- taiga
# volumes:
# - ./conf.json:/usr/share/nginx/html/conf.json
restart: unless-stopped
taiga-events:
image: taigaio/taiga-events:latest
environment:
RABBITMQ_USER: "${RABBITMQ_USER}"
RABBITMQ_PASS: "${RABBITMQ_PASS}"
TAIGA_SECRET_KEY: "${SECRET_KEY}"
networks:
- taiga
depends_on:
taiga-events-rabbitmq:
condition: service_started
restart: unless-stopped
taiga-events-rabbitmq:
image: rabbitmq:3.8-management-alpine
environment:
RABBITMQ_ERLANG_COOKIE: "${RABBITMQ_ERLANG_COOKIE}"
RABBITMQ_DEFAULT_USER: "${RABBITMQ_USER}"
RABBITMQ_DEFAULT_PASS: "${RABBITMQ_PASS}"
RABBITMQ_DEFAULT_VHOST: "${RABBITMQ_VHOST}"
hostname: "taiga-events-rabbitmq"
volumes:
- taiga-events-rabbitmq-data:/var/lib/rabbitmq
networks:
- taiga
restart: unless-stopped
taiga-protected:
image: taigaio/taiga-protected:latest
environment:
MAX_AGE: "${ATTACHMENTS_MAX_AGE}"
SECRET_KEY: "${SECRET_KEY}"
networks:
- taiga
restart: unless-stopped
taiga-gateway:
image: nginx:1.19-alpine
ports:
- "4190:80"
volumes:
- ./taiga-gateway/taiga.conf:/etc/nginx/conf.d/default.conf
- taiga-static-data:/taiga/static
- taiga-media-data:/taiga/media
networks:
- taiga
depends_on:
- taiga-front
- taiga-back
- taiga-events
restart: unless-stopped
volumes:
taiga-static-data:
taiga-media-data:
taiga-db-data:
taiga-async-rabbitmq-data:
taiga-events-rabbitmq-data:
networks:
taiga:
Gitea/Gitlab compose-bestand
Ik weet nog niet of ik gitea of gitlab wil gebruiken, dus maar even testen. Volgens gitea gebruikt het minder resources dan gitlab, maar verder is er niet veel verschil. Gitlab vraagt om een FQDN die je moet instellen in een gitlab.rb bestand. Daarna moet je iets goed instellen met de AAAA records. Het wil namelijk let's encrypt gebruiken om een certificaat in te stellen. Om dit uit te zetten moet je in gitlab.rb "https" veranderen in http".
Gitlab is te zwaar (gebruikt te veel geheugen) voor mijn huidige setup. Ik heb de VM 6GB gegeven, alleen gitlab wil al 4GB hebben, FreeIPA wil 1,2GB hebben. Ik ga dus Gitea gebruiken, aangezien dat minder hulpbronnen vraagt. Ik kan dan niet makkelijk pages draaien (misschien wel m.b.v. deze repo), maar de website met deze docs draait al via mijn publieke gitlab repo.
Het gitea compose-bestand staat hieronder:
networks:
gitea:
services:
server:
image: gitea/gitea:latest
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=postgres
- GITEA__database__HOST=db:5432
- GITEA__database__NAME=gitea
- GITEA__database__USER=gitea
- GITEA__database__PASSWD=/run/secrets/gitea_postgres_password
secrets:
- gitea_postgres_password
networks:
- gitea
volumes:
- gitea_gitea-server:/data
ports:
- "192.168.178.152:4300:3000"
- "192.168.178.152:4322:22"
depends_on:
- db
db:
image: postgres:14
restart: unless-stopped
environment:
- POSTGRES_USER=gitea
- POSTGRES_PASSWORD=/run/secrets/gitea_postgres_password
- POSTGRES_DB=gitea
secrets:
- gitea_postgres_password
networks:
- gitea
volumes:
- gitea_gitea-postgres:/var/lib/postgresql/data
volumes:
gitea_gitea-server:
external: true
gitea_gitea-postgres:
external: true
secrets:
gitea_postgres_password:
file: ./gitea_postgres_password.txt
Docusaurus
Voor docusaurus bestaat geen (officiele) docker image. Het is gewoon een npm app, dus je kan het wel zelf maken met een dockerfile enz. Voor een docusaurus voorbeeld zie deze gitlab repo.
Ik heb nu op mijn gitlab repo een werkende configuratie voor docusaurus staan. Deze notities staan ook online op www.gabbersaurewes.nl.
Nginx Proxy Manager of Caddy
Om de verschillende services achter *.gabbersaurewes.nl te zetten heb ik eerst nginx proxy manager geprobeerd. De DNS-records heb ik eerst geprobeerd in te stellen met BIND DNS, maar dat werkt niet stabiel. Ik heb de serverkast namelijk niet constant aanstaan en dan wordt de ingestelde DNS-server vergeten. Daarom heb ik bij de registrar de DNS-records ingesteld, dan nog werkt het alleen als ik Cloudflare/1.1.1.1 als DNS-server gebruik (werkt misschien ook met andere publieke DNS-servers). Het compose-bestand staat hieronder:
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
network_mode: host
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
Jammer genoeg werkt het niet met cockpit. Dus heb ik ook Caddy geprobeerd met dit compose-bestand:
services:
caddy:
image: caddy:latest
restart: unless-stopped
ports:
- "4080:80"
- "4443:443"
- "4443:443/udp"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile
- ./site:/srv
- caddy_data:/data
- caddy_config:/config
volumes:
caddy_data:
caddy_config:
Daarnaast heb ik een Caddyfile gemaakt met proxy's naar de .local domeinen. Dat werkt ook niet stabiel omdat dat ook met Bind DNS moet. Daarnaast werkt cockpit ook niet. Dus de proxy's moeten handmatig(er) met docker nginx.
FreeIPA
Voor FreeIPA gebruikt ik de freeipa.ansible_freeipa role. Aangezien ik de server en de VM's op een thuisnetwerk draai, stel ik de router in als forwarder DNS server. Mijn router doet alleen niet IPv6 DNS helemaal goed, dus ik moet ipaserver_forwarders: 192.168.1.1 instellen i.p.v. ipaserver_auto_forwarders: true.
Met de FreeIPA role heb ik een certificaat gegenereerd die getekend moet worden door de EJBCA CA. Het plaatst het certificaat in de dir met de playbook. Het verwacht een .crt-bestand en niet een pem-bestand zoals ik eerder handmatig heb gedaan.
EJBCA werkt nu ik heb een root CA gemaakt aan de hand van dit artikel, de CSR gesignd zoals ik eerder heb beschreven (alleen is de root pem niet nodig) en de pem chain om gezet naar het crt-bestand met openssl x509 -outform def -in Certificate\ Authority.pem -out server-chain.crt. Het ansible playbook verwacht een crt-bestand met dezelfde soort naam als het csr-bestand. Dus als de csr server-ipa.csr heet, is de crt server-chain.crt, als de csr aardbei-ipa.csr heet, is de crt aardbei-chain.crt.
Ansible verwacht weer dat het chain bestand in dezelfde dir als de playbook staat.
De playbooks werken niet of in ieder geval de playbook na het signen werkt niet. Handmatig werkt het wel, dus naar de server vm gaan ipa-server-install --external-ca doen, signen en dan ipa-server-install --external-cert-file=/pad/naar/subca.pem --external-cert-file=/pad/naar/rootca.pem doen. Het tweede playbook na het signgen geeft geen errors, maar het skipped wel een hoop tasks. Op de server is het installeren van freeipa succesvol, maar op de workstation werkt ipa-client-install niet. Het kan de server niet vinden als ldap, dns server of kerberos server.
Zitadel
Het zou mooi zijn als ik Zitadel kan gebruiken als SSO-oplossing. Er staat info hier.