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.