L'histoire de la façon dont j'ai configurĂ© les services dans Docker sur le Raspberry PI et pourquoi ce n'est peut-ĂȘtre pas la meilleure idĂ©e.
Introduction (ou comment tout a commencé)
Tout a commencé il y a longtempsIl y a quelques années. Il se trouve que je me suis retrouvé en Chine et que j'ai dû en quelque sorte entrer en contact avec le monde extérieur. Je ne faisais pas vraiment confiance aux VPN et aux proxys tiers, j'ai donc décidé d'élever DigitalOcean avec mon proxy. Il s'est avéré qu'au fil du temps, un serveur avec un proxy s'est développé avec différentes différences: du stockage de fichiers ( Syncthing) à CI ( Jenkins).
à son retour en Russie, il a été décidé de quitter DO pour une sorte d'auto-hébergement. Je ne voulais pas acheter un serveur séparé pour cela - c'est cher, et jusqu'à présent il n'y a pas besoin, pour cette raison j'ai pris Raspberry PI 4B. Naturellement, j'ai dû transférer tous les services de base de DO vers cette machine, qui fera l'objet de ce billet.
Introduction
Il était nécessaire de configurer les services suivants:
- Syncthing - synchronisation de fichiers
- Jenkins - CI
- Telegraf - |
- Influxdb - graphiques de CPU, GPU et autres
- Grafana - |
- Gogs - git
- Radicale - synchroniser calendriers / contacts
Outre:
- Il était censé stocker des fichiers et des données sur une paire de lecteurs flash USB3sous forme cryptée (LUKS)
- Toutes les interfaces Web étaient cachées derriÚre le proxy inverse Nginx
ProblĂšmes et nuances
Je voudrais immédiatement parler des problÚmes qui se sont posés lors de l'assemblage de tout cela et / ou qui se posent maintenant:
- Raspberry PI 1A, . , , â
- RaspberryPI 4B ( ) USB . â / . USB3
- , . ( ) ( " ")
- â syncthing, , /
- 60
â 502 ssh.
, Micro SD 16GB ( ) Raspbian. .
- Noobs
- Micro SD Fat32
- ( uNetbootin)
- Raspberry PI
. : GUI . GUI, ssh GUI .
()
Elementary OS GUI (GParted disks) . , :
, .
â ext4 LUKS.
- GParted
 - Device->- Create partition table...
- gpt
- Apply
- ext4
 
- gnome-disks(- sudo apt install gnome-disk-utility) (- Disks):
 - ()
- Format partition...
- Ext 4
- Password protect volume
- Next
- :
 
 
. , RaspberryPI . :
: /dev/sdb1 â , Device
dd if=/dev/urandom bs=4M count=1 of=/tmp/usb_decrypt_file
sudo cryptsetup luksAddKey /dev/sdb1 /tmp/usb_decrypt_file
.
: .
, . ()- /
, :
- (sudo apt update && sudo apt -y dist-upgrade)
- :
 - docker- docker-compose(- sudo apt -y install docker docker-compose)
- Nginx(- sudo apt -y install nginx). reverse-proxy
 
 - - (, - /root/cryptfiles; )
 
 
- /etc/crypttab:
 
 - usb1_crypt UUID=___UUID /root/cryptfiles/_- luks
 
 
- /etc/fstab
 
 - /dev/mapper/usb1_crypt /media/pi/usb1 ext4 defaults,nofail 0 2
 
 - : 
 - /dev/mapper/usb1_cryptâ- /dev/mapper/+ ( )- /etc/crypttab
- /media/pi/usb1â . (- mkdir /media/pi/usb1). â ,- /mnt- /media/$USER
 
 
- , 
 
 
 
Nginx
bash, reverse-proxy .
:
reverse-proxy nginx, â mydomain.com. nginx /etc/nginx, /etc/nginx/autocompile.
compile_apps_configs.sh#!/bin/bash
APPS=("syncthing" "grafana" "radicale" "git" "jenkins")
APPS_PROXIES=(http://localhost:8880 http://localhost:3000 http://localhost:8882 http://localhost:8883 http://localhost:8884)
HOSTNAMES=(my.domain)
conf_file="/etc/nginx/sites-available/autocompiled.conf"
ln_file="/etc/nginx/sites-enabled/autocompiled.conf"
echo "" > "$conf_file"
for app_index in ${!APPS[*]}
do
    app="${APPS[app_index]}"
    app_proxy="${APPS_PROXIES[app_index]}"
    for host in ${HOSTNAMES[*]}
    do
        echo "`./compile_config.sh "$host" "$app_proxy" $app`" >> "$conf_file"
        echo "" >> "$conf_file"
    done
done
ln -s "$conf_file" "$ln_file"
 compile_config.sh#!/bin/bash
DOMAIN_BASE="$1"
shift
PROXY_PATH=$(echo "$1" | sed -e "s/\//\\\\\//g")
PROXY_LOCATION=""
shift
HOSTNAME="$DOMAIN_BASE"
while [ -n "$1" ]
do
    case "$1" in
        "-pl") shift; PROXY_LOCATION="$(echo "$1" | sed -e "s/\//\\\\\//g")" ;;
        *) HOSTNAME="$1.$HOSTNAME" ;;
    esac
    shift
done
cat template.conf | sed "s/HOSTNAME_BASE/$DOMAIN_BASE/g" | sed "s/HOSTNAME/$HOSTNAME/g" | sed "s/PROXYPATH/$PROXY_PATH/g" | sed "s/PROXYLOCATION/$PROXY_LOCATION/"
 location_template.conf    location /PROXYLOCATION {
        proxy_pass PROXYPATH;
    }
 template.confserver {
    server_name "HOSTNAME";
    ssl_certificate /etc/letsencrypt/live/HOSTNAME_BASE/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/HOSTNAME_BASE/privkey.pem;
    listen 443 ssl;
    keepalive_timeout 60;
    ssl on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers "HIGH:!RC4:!aNULL:!MD5:!kEDH";
    add_header Strict-Transport-Security 'max-age=604800';
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-Host $host;
    proxy_set_header Host $host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Real-IP $remote_addr;
    # set max upload size
    client_max_body_size 4000M;
    sendfile on;
    send_timeout 600s;
    proxy_connect_timeout 600;
    location /PROXYLOCATION {
        proxy_pass_request_headers on;
        proxy_pass_request_body on;
        proxy_pass PROXYPATH;
    }
}
 , ./compile_apps_configs.sh nginx: sudo systemd reload nginx.
 Docker
, docker docker-compose:
sudo apt install docker docker-compose
yml . :
âââ doForAll
âââ gogs
â   âââ docker-compose.yml
â   âââ Dockerfile
â   âââ .env
âââ grafana
â   âââ configs
â   â   âââ influxdb.conf
â   â   âââ telegraf.conf
â   âââ docker-compose.yml
â   âââ .env
âââ jenkins
â   âââ docker-compose.yml
â   âââ .env
âââ makeFullUpdate
âââ radicale
â   âââ docker-compose.yml
â   âââ .env
âââ syncthing
    âââ docker-compose.yml
    âââ .env
, ( grafana â , â influxdb). .
, :
- .env- DATA_PATH
- Grafana- :
 - Telegraf.- .env- INFLUXDB_WRITE_USER_PASSWORD,- configs/telegraf.confâ- password
- Grafana.- .env- INFLUXDB_READ_USER_PASSWORD,- Grafana
 
.
root. :
sudo -i
mkdir -p /root/scripts/
touch "/root/scripts/monitor_startup_docker_container"
chmod 700 "/root/scripts/monitor_startup_docker_container"
nano "/root/scripts/monitor_startup_docker_container"
/root/scripts/monitor_startup_docker_container :
#!/bin/bash
function log() {
    echo `date`: "$@"
}
container_name="$1"
true=1
false=0
function restartContainer() {
    docker container restart "$1"
}
function checkContanerExitStatus() {
    container_name="$1"
    status_line="`docker container ps -a --filter "name=$container_name" --filter "exited=255" | grep "$container_name"`"
    [[ -z "$status_line" ]] && echo $false || echo $true
}
function checkContanerStatusIsEqual() {
    container_name="$1"
    container_dest_status="$2"
    status_line="`docker container ps -a --filter "name=$container_name" --filter "status=$container_dest_status" | grep "$container_name"`"
    [[ -z "$status_line" ]] && echo $false || echo $true
}
function isRunning() {
    echo "`checkContanerStatusIsEqual "$container_name" "running"`"
}
while [[ "`isRunning`" != "$true" ]]; do
    log check cycle "$container_name"
    if [ "`checkContanerStatusIsEqual "$container_name" "exited"`" == "$true" -o "`checkContanerStatusIsEqual "$container_name" "dead"`" == "$true" ]; then
        log restart "$container_name"
        restartContainer "$container_name"
    fi
    if [[ "`isRunning`" -eq "$false" ]]; then
        sleep 5
    else
        sleep 120
    fi
done
log started "$container_name"
crontab . root:
`crontab -e`@reboot rm /root/startup_docker_logs
1/10 * * * * /root/scripts/monitor_startup_docker_container telegraf >> /root/startup_docker_logs
2/10 * * * * /root/scripts/monitor_startup_docker_container influxdb >> /root/startup_docker_logs
3/10 * * * * /root/scripts/monitor_startup_docker_container grafana >> /root/startup_docker_logs
3/10 * * * * /root/scripts/monitor_startup_docker_container jenkins >> /root/startup_docker_logs
3/10 * * * * /root/scripts/monitor_startup_docker_container gogs >> /root/startup_docker_logs
1/10 * * * * /root/scripts/monitor_startup_docker_container radicale >> /root/startup_docker_logs
2/10 * * * * /root/scripts/monitor_startup_docker_container syncthing >> /root/startup_docker_logs
 , , 
- Configurer l'accĂšs Ă  SSHla framboise: il existe un grand nombre de tutoriels sur ce sujet, voici un exemple avec DigitalOcean
- Configurer les services eux-mĂȘmes
- Achat et configuration de DNS pour les domaines
Je serai heureux de faire des commentaires et des commentaires utiles.