Kisah tentang bagaimana saya mengkonfigurasi layanan di buruh pelabuhan pada Raspberry PI dan mengapa ini mungkin bukan ide terbaik.
Pendahuluan (atau bagaimana semuanya dimulai)
Semua dimulai dahulu kalabeberapa tahun yang lalu. Kebetulan saya berakhir di Tiongkok dan saya harus menghubungi dunia luar. Saya tidak benar-benar mempercayai VPN dan proxy pihak ketiga, jadi saya memutuskan untuk meningkatkan DigitalOcean dengan proxy saya. Kebetulan dari waktu ke waktu, server dengan proxy telah berkembang dengan perbedaan yang berbeda: dari penyimpanan file ( Syncthing
) ke CI ( Jenkins
).
Setelah kembali ke Rusia, diputuskan untuk meninggalkan DO untuk beberapa jenis hosting sendiri. Saya tidak ingin membeli server terpisah untuk ini - harganya mahal, dan sejauh ini tidak perlu, untuk alasan ini saya menggunakan Raspberry PI 4B. Secara alami, saya harus mentransfer semua layanan dasar dari DO ke mesin ini, yang akan menjadi subjek dari posting ini.
Pendahuluan
Itu perlu untuk mengkonfigurasi layanan berikut:
- Sinkroni - sinkronisasi file
- Jenkins - CI
- Telegraf - |
- Influxdb - CPU, GPU, dan banyak lagi
- Grafana - |
- Gogs - git
- Radicale - sinkronisasi kalender / kontak
Selain:
- Seharusnya menyimpan file dan data pada sepasang flash drive
USB3
dalam bentuk terenkripsi ( LUKS
) - Semua antarmuka web disembunyikan di balik proksi terbalik Nginx
Masalah dan Nuansa
Saya ingin segera berbicara tentang masalah yang muncul selama pertemuan semua ini dan / atau muncul sekarang:
- 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
.
: .
, . ()- /
Raspberry PI
, :
- (
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
, , Rata-rata, hampir tidak ada perawatan. Apa yang tidak tercakup dalam artikel ini:
- Mengkonfigurasi akses ke
SSH
raspberry: ada banyak tutorial tentang topik ini, berikut adalah contoh dengan DigitalOcean - Konfigurasikan layanan itu sendiri
- Membeli dan Mengkonfigurasi DNS untuk Domain
Saya akan senang memberikan komentar dan komentar yang bermanfaat.