Skip to content
Snippets Groups Projects
Unverified Commit e0beb568 authored by vmaubert's avatar vmaubert Committed by GitHub
Browse files

chore(infra): supporte l’installation d’une machine neuve (#767)

parent 6bd20036
No related branches found
No related tags found
No related merge requests found
Showing
with 228 additions and 514 deletions
......@@ -2,10 +2,11 @@ FROM node:20.3-alpine
WORKDIR /
# on profite que
# - l'utilisateur a le même id sur toutes les machines
# - l'utilisateur a le même uid/gid sur toutes les machines
# - ansible crée les dossiers avec les bons droits
RUN apk add make && \
adduser -u 1002 -D nonroot && \
addgroup -g 1002 nonroot && \
adduser -u 1002 -D -G nonroot nonroot && \
mkdir node_modules && \
chown nonroot:nonroot node_modules
......
# Première initialisation
Lors de la première installation de camino (sur ovh), un utilisateur "debian" est crée par défaut, avec l'accès ssh.
Il faut forcer ansible à utiliser cet utilisateur, via cette commande: `ansible-playbook -i inventory_{dev|preprod|prod} -u debian deploy.yml`
Le script va créer les utilisateurs qui auront les droits de gérer la machine, puis supprimer l'utilisateur "debian".
ATTENTION, le script va planter, il faudra:
- vous connecter en ssh avec votre login pour pouvoir changer votre mot de passe
- relancer ansible normalement (make dev|preprod|prod)
- déployer la bonne version de camino (via github actions)
- aller sur la machine, et lancer le processus de restauration des backups --> `./srv/scripts/restore-last-backup`
---
- hosts: servers
vars:
git_user_uid: 1002
# L'UID doit être le même que dans le Dockerfile.api
camino_user_uid: 1002
# Le GID doit être le même que dans le Dockerfile.api
camino_user_gid: 1002
roles:
- role: swap
when: ansible_swaptotal_mb < 1
- role: init
- role: user
- role: init
- role: nginx
- role: camino
- role: devAndPreprod
when: env != 'prod'
- role: prod
when: env == 'prod'
......@@ -4,5 +4,4 @@ dev.camino.beta.gouv.fr
[servers:vars]
env=dev
ansible_port=212
ansible_python_interpreter=/usr/bin/python3
\ No newline at end of file
ansible_python_interpreter=/usr/bin/python3
......@@ -3,5 +3,4 @@ preprod.camino.beta.gouv.fr
[servers:vars]
env=preprod
ansible_port=212
ansible_python_interpreter=/usr/bin/python3
\ No newline at end of file
......@@ -3,5 +3,4 @@ camino.beta.gouv.fr
[servers:vars]
env=prod
ansible_port=212
ansible_python_interpreter=/usr/bin/python3
\ No newline at end of file
......@@ -3,7 +3,31 @@
ansible.builtin.file:
path: /srv/www/camino/
state: directory
owner: git
owner: camino
group: users
mode: u=rwx,g=rwx,o=rx
become: True
- name: Donne les bons droits sur le dossier backups
ansible.builtin.file:
path: /srv/backups
state: directory
owner: camino
group: users
mode: u=rwx,g=rwx,o=rx
become: True
- name: Donne les bons droits sur le dossier dump
ansible.builtin.file:
path: /srv/backups/dump
state: directory
owner: camino
group: users
mode: u=rwx,g=rwx,o=rx
become: True
- name: Donne les bons droits sur le dossier files
ansible.builtin.file:
path: /srv/backups/files
state: directory
owner: camino
group: users
mode: u=rwx,g=rwx,o=rx
become: True
......@@ -11,7 +35,7 @@
ansible.builtin.copy:
src: ../../../../docker-compose.yml
dest: /srv/www/camino/docker-compose.yml
owner: git
owner: camino
group: users
mode: u=rw,g=r,o=r
become: True
......@@ -20,7 +44,7 @@
src: env
dest: /srv/www/camino/.env
mode: u=rw,g=r,o=r
owner: git
owner: camino
group: users
become: True
- name: Installe le jar keycloak france connect
......@@ -28,7 +52,7 @@
src: keycloak-franceconnect-6.0.0.jar
dest: /srv/www/camino/keycloak-franceconnect-6.0.0.jar
mode: u=rwx,g=rw,o=r
owner: git
owner: camino
group: users
become: True
- name: Installe le jar keycloak bcrypt
......@@ -36,14 +60,14 @@
src: keycloak-bcrypt-1.6.0.jar
dest: /srv/www/camino/keycloak-bcrypt-1.6.0.jar
mode: u=rwx,g=rw,o=r
owner: git
owner: camino
group: users
become: True
- name: Crée le dossier pour le theme keycloak
ansible.builtin.file:
path: /srv/www/camino/keycloak_theme
state: directory
owner: git
owner: camino
group: users
mode: u=rwx,g=rwx,o=rx
become: True
......@@ -54,15 +78,37 @@
delete: True
times: False
perms: False
rsync_opts:
- "--chown=camino:users"
- name: Donne les bons droits au dossier du theme keycloak
ansible.builtin.file:
path: /srv/www/camino/keycloak_theme
state: directory
owner: git
owner: camino
group: users
mode: u=rwx,g=rwx,o=rx
recurse: True
become: True
- name: Restauration des backups
block:
- name: Ajoute le script pour pouvoir mettre les données de production sur cet environnement
template:
src: restore-last-backup
dest: /srv/scripts/
mode: u=rwx,g=rx,o=r
owner: camino
group: users
become: True
- name: Ajoute le job de restauration du backup de la prod
ansible.builtin.cron:
name: "backup"
minute: "0"
hour: "6"
weekday: "0"
job: "/srv/scripts/restore-last-backup"
user: camino
become: True
when: env == 'dev'
- name: Daily
block:
- name: Ajoute le script pour pouvoir lancer le daily
......@@ -70,7 +116,7 @@
src: daily
dest: /srv/scripts/
mode: u=rwx,g=rx,o=r
owner: git
owner: camino
group: users
become: True
- name: Ajoute le cron de daily
......@@ -79,7 +125,7 @@
minute: "0"
hour: "4"
job: "/srv/scripts/daily"
user: git
user: camino
become: True
- name: Monthly
block:
......@@ -88,7 +134,7 @@
src: monthly
dest: /srv/scripts/
mode: u=rwx,g=rx,o=r
owner: git
owner: camino
group: users
become: True
- name: Ajoute le cron de monthly
......@@ -98,7 +144,7 @@
hour: "6"
day: "1"
job: "/srv/scripts/monthly"
user: git
user: camino
become: True
- name: Ajoute le cron de nettoyage
ansible.builtin.cron:
......@@ -106,7 +152,7 @@
minute: "0"
hour: "5"
job: "rm -rf /srv/www/camino/files/downloads/*"
user: git
user: camino
become: True
- name: Continuous deployment
block:
......@@ -119,7 +165,7 @@
ansible.builtin.file:
path: /srv/www/cd
state: directory
owner: git
owner: camino
group: users
mode: u=rwx,g=rwx,o=r
become: True
......@@ -127,7 +173,7 @@
ansible.builtin.copy:
src: ../../cd/target/x86_64-unknown-linux-gnu/release/cd
dest: /srv/www/cd/cd
owner: git
owner: camino
group: users
mode: u=rwx,g=rwx,o=rx
become: True
......
#!/bin/bash
set eufo -pipefail
if [ "$(id -u)" != "{{git_user_uid}}" ]; then
echo "This script must be run as git" 1>&2
if [ "$(id -u)" != "{{camino_user_uid}}" ]; then
echo "This script must be run as user 'camino'" 1>&2
exit 1
fi
......
---
- name: Ajoute le script pour pouvoir mettre les données de production sur cet environnement
template:
src: apply-prod
dest: /srv/scripts/
mode: u=rwx,g=rx,o=r
owner: git
group: users
become: True
- name: Donne les droits du dossier de backup à l'utilisateur "git"
file:
path: /srv/backups
owner: git
group: users
become: True
- name: Ajoute le job de restauration du backup de la prod
ansible.builtin.cron:
name: "backup"
minute: "0"
hour: "6"
weekday: "0"
job: "/srv/scripts/apply-prod"
user: git
become: True
when: env == 'dev'
\ No newline at end of file
---
- name: Set a hostname
ansible.builtin.hostname:
name: "camino-{{ env }}"
become: True
- name: Set timezone to Europe/Paris
community.general.timezone:
name: Europe/Paris
become: True
- name: Upgrade machine
ansible.builtin.apt:
upgrade: safe
......@@ -9,23 +17,51 @@
name: rsync
state: present
become: True
- name: Install docker
ansible.builtin.apt:
name: docker-ce
state: latest
become: True
- name: Install docker client
- name: Install cron
ansible.builtin.apt:
name: docker-ce-cli
state: latest
name: cron
state: present
become: True
- name: Configure la machine pour installer docker
block:
- name: Install tools for apt
ansible.builtin.apt:
name:
- ca-certificates
- curl
- gnupg
state: present
become: True
- name: Ajoute les clés de signature pour docker
ansible.builtin.apt_key:
url: "https://download.docker.com/linux/{{ ansible_distribution | lower }}/gpg"
keyring: /etc/apt/trusted.gpg.d/docker.gpg
state: present
become: True
- name: Ajoute le repository pour pouvoir installer docker
ansible.builtin.apt_repository:
repo: "deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/docker.gpg] https://download.docker.com/linux/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} stable"
state: present
update_cache: True
filename: docker
become: True
- name: Install docker
ansible.builtin.apt:
name: docker-ce
state: latest
become: True
- name: Install docker client
ansible.builtin.apt:
name: docker-ce-cli
state: latest
become: True
- name: Install docker compose
ansible.builtin.get_url:
url: https://github.com/docker/compose/releases/download/v2.11.2/docker-compose-linux-x86_64
checksum: sha256:1178848502b0771b96895febeb4b1736acd5019c4ed71a8efbabf6915185fe8a
dest: /usr/local/bin/docker-compose
mode: u=rwx,g=rx,o=rx
owner: git
owner: camino
group: users
become: True
- name: Ajoute les variables liées au bon environnement
......@@ -46,6 +82,6 @@
src: restic_data
dest: /srv/scripts/
mode: u=rwx,g=rx,o=r
owner: git
owner: camino
group: users
become: True
\ No newline at end of file
......@@ -2,11 +2,9 @@ version: '3'
services:
nginx:
image: nginx:1.22.0
labels:
com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy: "true"
container_name: nginx
nginx-proxy:
image: nginxproxy/nginx-proxy:1.3.1
container_name: nginx-proxy
restart: unless-stopped
logging:
options:
......@@ -16,40 +14,33 @@ services:
- "80:80"
- "443:443"
volumes:
- /srv/www/nginx-proxy/conf.d:/etc/nginx/conf.d
- /srv/www/nginx-proxy/vhost.d:/etc/nginx/vhost.d
- /srv/www/nginx-proxy/html:/usr/share/nginx/html
- /srv/www/nginx-proxy/certs:/etc/nginx/certs:ro
nginx-gen:
image: jwilder/docker-gen:0.9-debian
command: -notify-sighup nginx -watch -wait 5s:30s /etc/docker-gen/templates/nginx.tmpl /etc/nginx/conf.d/default.conf
container_name: nginx-gen
restart: unless-stopped
volumes:
- /srv/www/nginx-proxy/conf.d:/etc/nginx/conf.d
- /srv/www/nginx-proxy/vhost.d:/etc/nginx/vhost.d
- /srv/www/nginx-proxy/html:/usr/share/nginx/html
- /srv/www/nginx-proxy/certs:/etc/nginx/certs:ro
- /srv/www/nginx-proxy/proxy.conf:/etc/nginx/proxy.conf
- certs:/etc/nginx/certs
- vhost:/etc/nginx/vhost.d
- html:/usr/share/nginx/html
- /var/run/docker.sock:/tmp/docker.sock:ro
- /srv/www/nginx-proxy/nginx.tmpl:/etc/docker-gen/templates/nginx.tmpl:ro
nginx-letsencrypt:
image: jrcs/letsencrypt-nginx-proxy-companion:2.2.1
container_name: nginx-letsencrypt
nginx-proxy-acme:
image: nginxproxy/acme-companion:2.2.8
container_name: nginx-proxy-acme
restart: unless-stopped
volumes_from:
- nginx-proxy
volumes:
- /srv/www/nginx-proxy/conf.d:/etc/nginx/conf.d
- /srv/www/nginx-proxy/vhost.d:/etc/nginx/vhost.d
- /srv/www/nginx-proxy/html:/usr/share/nginx/html
- /srv/www/nginx-proxy/certs:/etc/nginx/certs:rw
- /var/run/docker.sock:/var/run/docker.sock:ro
- acme:/etc/acme.sh
environment:
NGINX_DOCKER_GEN_CONTAINER: "nginx-gen"
NGINX_PROXY_CONTAINER: "nginx"
NGINX_PROXY_CONTAINER: "nginx-proxy"
DEFAULT_EMAIL: "{{LETSENCRYPT_EMAIL}}"
networks:
default:
external:
name: nginx-proxy
volumes:
conf:
vhost:
html:
certs:
acme:
{{ $CurrentContainer := where $ "ID" .Docker.CurrentContainerID | first }}
{{ define "upstream" }}
{{ if .Address }}
{{/* If we got the containers from swarm and this container's port is published to host, use host IP:PORT */}}
{{ if and .Container.Node.ID .Address.HostPort }}
# {{ .Container.Node.Name }}/{{ .Container.Name }}
server {{ .Container.Node.Address.IP }}:{{ .Address.HostPort }};
{{/* If there is no swarm node or the port is not published on host, use container's IP:PORT */}}
{{ else if .Network }}
# {{ .Container.Name }}
server {{ .Network.IP }}:{{ .Address.Port }};
{{ end }}
{{ else if .Network }}
# {{ .Container.Name }}
{{ if .Network.IP }}
server {{ .Network.IP }} down;
{{ else }}
server 127.0.0.1 down;
{{ end }}
{{ end }}
{{ end }}
{{ define "ssl_policy" }}
{{ if eq .ssl_policy "Mozilla-Modern" }}
ssl_protocols TLSv1.3;
{{/* nginx currently lacks ability to choose ciphers in TLS 1.3 in configuration, see https://trac.nginx.org/nginx/ticket/1529 /*}}
{{/* a possible workaround can be modify /etc/ssl/openssl.cnf to change it globally (see https://trac.nginx.org/nginx/ticket/1529#comment:12 ) /*}}
{{/* explicitly set ngnix default value in order to allow single servers to override the global http value */}}
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers off;
{{ else if eq .ssl_policy "Mozilla-Intermediate" }}
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;
{{ else if eq .ssl_policy "Mozilla-Old" }}
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
{{ else if eq .ssl_policy "AWS-TLS-1-2-2017-01" }}
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:AES128-GCM-SHA256:AES128-SHA256:AES256-GCM-SHA384:AES256-SHA256';
ssl_prefer_server_ciphers on;
{{ else if eq .ssl_policy "AWS-TLS-1-1-2017-01" }}
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
ssl_prefer_server_ciphers on;
{{ else if eq .ssl_policy "AWS-2016-08" }}
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA';
ssl_prefer_server_ciphers on;
{{ else if eq .ssl_policy "AWS-2015-05" }}
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
{{ else if eq .ssl_policy "AWS-2015-03" }}
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA:DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
{{ else if eq .ssl_policy "AWS-2015-02" }}
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES128-SHA256:AES128-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:DHE-DSS-AES128-SHA';
ssl_prefer_server_ciphers on;
{{ end }}
{{ end }}
client_max_body_size 30m;
# If we receive X-Forwarded-Proto, pass it through; otherwise, pass along the
# scheme used to connect to this server
map $http_x_forwarded_proto $proxy_x_forwarded_proto {
default $http_x_forwarded_proto;
'' $scheme;
}
# If we receive X-Forwarded-Port, pass it through; otherwise, pass along the
# server port the client connected to
map $http_x_forwarded_port $proxy_x_forwarded_port {
default $http_x_forwarded_port;
'' $server_port;
}
# If we receive Upgrade, set Connection to "upgrade"; otherwise, delete any
# Connection header that may have been passed to this server
map $http_upgrade $proxy_connection {
default upgrade;
'' close;
}
# Apply fix for very long server names
server_names_hash_bucket_size 128;
# Default dhparam
{{ if (exists "/etc/nginx/dhparam/dhparam.pem") }}
ssl_dhparam /etc/nginx/dhparam/dhparam.pem;
{{ end }}
# Set appropriate X-Forwarded-Ssl header
map $scheme $proxy_x_forwarded_ssl {
default off;
https on;
}
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
log_format vhost '$host $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent"';
access_log off;
{{/* Get the SSL_POLICY defined by this container, falling back to "Mozilla-Intermediate" */}}
{{ $ssl_policy := or ($.Env.SSL_POLICY) "Mozilla-Intermediate" }}
{{ template "ssl_policy" (dict "ssl_policy" $ssl_policy) }}
{{ if $.Env.RESOLVERS }}
resolver {{ $.Env.RESOLVERS }};
{{ end }}
{{ if (exists "/etc/nginx/proxy.conf") }}
include /etc/nginx/proxy.conf;
{{ else }}
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
{{ end }}
{{ $enable_ipv6 := eq (or ($.Env.ENABLE_IPV6) "") "true" }}
server {
server_name _; # This is just an invalid value which will never trigger on a real hostname.
listen 80;
{{ if $enable_ipv6 }}
listen [::]:80;
{{ end }}
access_log /var/log/nginx/access.log vhost;
return 503;
}
{{ if (and (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
server {
server_name _; # This is just an invalid value which will never trigger on a real hostname.
listen 443 ssl http2;
{{ if $enable_ipv6 }}
listen [::]:443 ssl http2;
{{ end }}
access_log /var/log/nginx/access.log vhost;
return 503;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/default.crt;
ssl_certificate_key /etc/nginx/certs/default.key;
}
{{ end }}
{{ range $host, $containers := groupByMulti $ "Env.VIRTUAL_HOST" "," }}
{{ $host := trim $host }}
{{ $is_regexp := hasPrefix "~" $host }}
{{ $upstream_name := when $is_regexp (sha1 $host) $host }}
# {{ $host }}
upstream {{ $upstream_name }} {
{{ range $container := $containers }}
{{ $addrLen := len $container.Addresses }}
{{ range $knownNetwork := $CurrentContainer.Networks }}
{{ range $containerNetwork := $container.Networks }}
{{ if (and (ne $containerNetwork.Name "ingress") (or (eq $knownNetwork.Name $containerNetwork.Name) (eq $knownNetwork.Name "host"))) }}
## Can be connected with "{{ $containerNetwork.Name }}" network
{{/* If only 1 port exposed, use that */}}
{{ if eq $addrLen 1 }}
{{ $address := index $container.Addresses 0 }}
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
{{/* If more than one port exposed, use the one matching VIRTUAL_PORT env var, falling back to standard web port 80 */}}
{{ else }}
{{ $port := coalesce $container.Env.VIRTUAL_PORT "80" }}
{{ $address := where $container.Addresses "Port" $port | first }}
{{ template "upstream" (dict "Container" $container "Address" $address "Network" $containerNetwork) }}
{{ end }}
{{ else }}
# Cannot connect to network of this container
server 127.0.0.1 down;
{{ end }}
{{ end }}
{{ end }}
{{ end }}
}
{{ $default_host := or ($.Env.DEFAULT_HOST) "" }}
{{ $default_server := index (dict $host "" $default_host "default_server") $host }}
{{/* Get the VIRTUAL_PROTO defined by containers w/ the same vhost, falling back to "http" */}}
{{ $proto := trim (or (first (groupByKeys $containers "Env.VIRTUAL_PROTO")) "http") }}
{{/* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external" */}}
{{ $network_tag := or (first (groupByKeys $containers "Env.NETWORK_ACCESS")) "external" }}
{{/* Get the HTTPS_METHOD defined by containers w/ the same vhost, falling back to "redirect" */}}
{{ $https_method := or (first (groupByKeys $containers "Env.HTTPS_METHOD")) "redirect" }}
{{/* Get the SSL_POLICY defined by containers w/ the same vhost, falling back to empty string (use default) */}}
{{ $ssl_policy := or (first (groupByKeys $containers "Env.SSL_POLICY")) "" }}
{{/* Get the HSTS defined by containers w/ the same vhost, falling back to "max-age=31536000" */}}
{{ $hsts := or (first (groupByKeys $containers "Env.HSTS")) "max-age=31536000" }}
{{/* Get the VIRTUAL_ROOT By containers w/ use fastcgi root */}}
{{ $vhost_root := or (first (groupByKeys $containers "Env.VIRTUAL_ROOT")) "/var/www/public" }}
{{/* Get the first cert name defined by containers w/ the same vhost */}}
{{ $certName := (first (groupByKeys $containers "Env.CERT_NAME")) }}
{{/* Get the best matching cert by name for the vhost. */}}
{{ $vhostCert := (closest (dir "/etc/nginx/certs") (printf "%s.crt" $host))}}
{{/* vhostCert is actually a filename so remove any suffixes since they are added later */}}
{{ $vhostCert := trimSuffix ".crt" $vhostCert }}
{{ $vhostCert := trimSuffix ".key" $vhostCert }}
{{/* Use the cert specified on the container or fallback to the best vhost match */}}
{{ $cert := (coalesce $certName $vhostCert) }}
{{ $is_https := (and (ne $https_method "nohttps") (ne $cert "") (exists (printf "/etc/nginx/certs/%s.crt" $cert)) (exists (printf "/etc/nginx/certs/%s.key" $cert))) }}
{{ if $is_https }}
{{ if eq $https_method "redirect" }}
server {
server_name {{ $host }};
listen 80 {{ $default_server }};
{{ if $enable_ipv6 }}
listen [::]:80 {{ $default_server }};
{{ end }}
access_log /var/log/nginx/access.log vhost;
return 301 https://$host$request_uri;
}
{{ end }}
server {
server_name {{ $host }};
listen 443 ssl http2 {{ $default_server }};
{{ if $enable_ipv6 }}
listen [::]:443 ssl http2 {{ $default_server }};
{{ end }}
access_log /var/log/nginx/access.log vhost;
{{ if eq $network_tag "internal" }}
# Only allow traffic from internal clients
include /etc/nginx/network_internal.conf;
{{ end }}
{{ template "ssl_policy" (dict "ssl_policy" $ssl_policy) }}
ssl_session_timeout 5m;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_certificate /etc/nginx/certs/{{ (printf "%s.crt" $cert) }};
ssl_certificate_key /etc/nginx/certs/{{ (printf "%s.key" $cert) }};
{{ if (exists (printf "/etc/nginx/certs/%s.dhparam.pem" $cert)) }}
ssl_dhparam {{ printf "/etc/nginx/certs/%s.dhparam.pem" $cert }};
{{ end }}
{{ if (exists (printf "/etc/nginx/certs/%s.chain.pem" $cert)) }}
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate {{ printf "/etc/nginx/certs/%s.chain.pem" $cert }};
{{ end }}
{{ if (not (or (eq $https_method "noredirect") (eq $hsts "off"))) }}
add_header Strict-Transport-Security "{{ trim $hsts }}" always;
{{ end }}
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
include {{ printf "/etc/nginx/vhost.d/%s" $host }};
{{ else if (exists "/etc/nginx/vhost.d/default") }}
include /etc/nginx/vhost.d/default;
{{ end }}
location / {
{{ if eq $proto "uwsgi" }}
include uwsgi_params;
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ else if eq $proto "fastcgi" }}
root {{ trim $vhost_root }};
include fastcgi_params;
fastcgi_pass {{ trim $upstream_name }};
{{ else }}
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ end }}
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
auth_basic "Restricted {{ $host }}";
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }};
{{ end }}
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
include /etc/nginx/vhost.d/default_location;
{{ end }}
}
}
{{ end }}
{{ if or (not $is_https) (eq $https_method "noredirect") }}
server {
server_name {{ $host }};
listen 80 {{ $default_server }};
{{ if $enable_ipv6 }}
listen [::]:80 {{ $default_server }};
{{ end }}
access_log /var/log/nginx/access.log vhost;
{{ if eq $network_tag "internal" }}
# Only allow traffic from internal clients
include /etc/nginx/network_internal.conf;
{{ end }}
{{ if (exists (printf "/etc/nginx/vhost.d/%s" $host)) }}
include {{ printf "/etc/nginx/vhost.d/%s" $host }};
{{ else if (exists "/etc/nginx/vhost.d/default") }}
include /etc/nginx/vhost.d/default;
{{ end }}
location / {
{{ if eq $proto "uwsgi" }}
include uwsgi_params;
uwsgi_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ else if eq $proto "fastcgi" }}
root {{ trim $vhost_root }};
include fastcgi_params;
fastcgi_pass {{ trim $upstream_name }};
{{ else }}
proxy_pass {{ trim $proto }}://{{ trim $upstream_name }};
{{ end }}
{{ if (exists (printf "/etc/nginx/htpasswd/%s" $host)) }}
auth_basic "Restricted {{ $host }}";
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" $host) }};
{{ end }}
{{ if (exists (printf "/etc/nginx/vhost.d/%s_location" $host)) }}
include {{ printf "/etc/nginx/vhost.d/%s_location" $host}};
{{ else if (exists "/etc/nginx/vhost.d/default_location") }}
include /etc/nginx/vhost.d/default_location;
{{ end }}
}
}
{{ if (and (not $is_https) (exists "/etc/nginx/certs/default.crt") (exists "/etc/nginx/certs/default.key")) }}
server {
server_name {{ $host }};
listen 443 ssl http2 {{ $default_server }};
{{ if $enable_ipv6 }}
listen [::]:443 ssl http2 {{ $default_server }};
{{ end }}
access_log /var/log/nginx/access.log vhost;
return 500;
ssl_certificate /etc/nginx/certs/default.crt;
ssl_certificate_key /etc/nginx/certs/default.key;
}
{{ end }}
{{ end }}
{{ end }}
client_max_body_size 30m;
gzip_types text/plain text/css application/javascript application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
# HTTP 1.1 support
proxy_http_version 1.1;
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
---
- file:
path: /srv/www/nginx-proxy
group: users
state: directory
owner: camino
mode: u=rwx,g=rwx,o=r
become: True
- name: Met en place le docker-compose
ansible.builtin.copy:
src: docker-compose.yml
dest: /srv/www/nginx-proxy/docker-compose.yml
owner: git
owner: camino
group: users
mode: u=rw,g=r,o=r
become: True
- name: Ajoute le fichier de template nginx
ansible.builtin.copy:
src: nginx.tmpl
dest: /srv/www/nginx-proxy/nginx.tmpl
owner: git
src: proxy.conf
dest: /srv/www/nginx-proxy/proxy.conf
owner: camino
group: users
mode: u=rw,g=r,o=r
become: True
- name: Install python-pip
- name: Install docker support for python
ansible.builtin.apt:
name: python3-pip
state: present
name: python3-docker
become: True
- name: Install docker support for python
ansible.builtin.pip:
name:
- docker
- docker-compose
- name: Create a network
community.docker.docker_network:
name: nginx-proxy
# TODO 2023-10-12 https://github.com/ansible-collections/community.docker/issues/672
- name: Create and start services
community.docker.docker_compose:
project_src: /srv/www/nginx-proxy
\ No newline at end of file
shell:
chdir: /srv/www/nginx-proxy
cmd: "docker-compose up -d"
\ No newline at end of file
......@@ -4,7 +4,7 @@
src: backup
dest: /srv/scripts/
mode: u=rwx,g=rx,o=r
owner: git
owner: camino
group: users
become: True
- name: Ajoute le job de backup de la prod
......@@ -13,7 +13,7 @@
minute: "0"
hour: "2"
job: "/srv/scripts/backup"
user: git
user: camino
become: True
- name: Configure le S3 pour les backups
block:
......@@ -27,7 +27,7 @@
src: owner.cfg
dest: /srv/scripts/
mode: u=rwx,g=rx,o=r
owner: git
owner: camino
group: users
become: True
register: owner
......@@ -36,7 +36,7 @@
src: bucket-ro.json
dest: /srv/scripts/
mode: u=rwx,g=rx,o=r
owner: git
owner: camino
group: users
become: True
register: bucket_ro
......
......@@ -3,8 +3,8 @@ set eufo -pipefail
source /srv/scripts/restic_data
if [ "$(id -u)" != "{{git_user_uid}}" ]; then
echo "This script must be run as git" 1>&2
if [ "$(id -u)" != "{{camino_user_uid}}" ]; then
echo "This script must be run as user 'camino'" 1>&2
exit 1
fi
# backup
......@@ -15,6 +15,6 @@ docker exec camino_api_db pg_dump --clean --if-exists --format=d --no-owner --no
# sauvegarde les fichiers
rsync --delete -r /srv/www/camino/files/ /srv/backups/files
chown git:users -R /srv/backups/
chown camino:users -R /srv/backups/
restic backup /srv/backups/
\ No newline at end of file
......@@ -11,7 +11,7 @@
update_password: "on_create"
# 'caminimino' -> seul l'utilisateur avec la bonne clef ssh peut se connecter + force le changement de mot de passe au login donc on peut laisser ce mot de passe public
password: "$6$MYtufjmobe/GD$fKrKSXr0R6Zm4ATQqAFJXsXRSOLcOVnkdwfNiDw3nnsBWdojA4BW4TTeVmQP48j6bRck./BnQ4/fRlqtvqavP1"
groups: "{{ camino_dev.nom }}, git, users, docker, sudo"
groups: "{{ camino_dev.nom }}, camino, users, docker, sudo"
become: True
register: create_user
- name: "{{ camino_dev.nom }}: force le changement du mot de passe"
......
---
- name: Ajout utilisateurs
include_tasks: "devs.yml"
loop: "{{ users }}"
loop_control:
loop_var: camino_dev
- name: ajoute le groupe "git"
- name: ajoute le groupe "camino"
ansible.builtin.group:
name: camino
state: present
# Le GID doit être le même que dans le Dockerfile.api
gid: "{{ camino_user_gid }}"
become: True
- name: ajoute le groupe "docker"
ansible.builtin.group:
name: git
name: docker
state: present
gid: "{{ git_user_uid }}"
become: True
- name: ajoute l'utilisateur 'git'
- name: ajoute l'utilisateur 'camino'
ansible.builtin.user:
name: git
comment: Git
name: camino
comment: Camino
shell: "/bin/bash"
# L'UID doit être le même que dans le Dockerfile.api
uid: "{{ git_user_uid }}"
groups: git, users, docker
uid: "{{ camino_user_uid }}"
groups: camino, users, docker
become: True
- name: Ajout utilisateurs
include_tasks: "devs.yml"
loop: "{{ users }}"
loop_control:
loop_var: camino_dev
- file:
path: /srv/www/camino/files
group: users
state: directory
recurse: True
owner: git
owner: camino
mode: u=rwx,g=rwx,o=r
become: True
\ No newline at end of file
become: True
- name: supprime l'utilisateur debian
ansible.builtin.user:
name: debian
state: absent
remove: True
force: True
become: True
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment