Init
This commit is contained in:
parent
fa80d14dba
commit
3847f18792
11 changed files with 536 additions and 1 deletions
|
@ -1,3 +1,8 @@
|
|||
# lxdXX.benpro.fr
|
||||
|
||||
Pyinfra that deploy my LXD server.
|
||||
Pyinfra that deploy my LXD server.
|
||||
|
||||
```
|
||||
pyinfra inventory.py setup-base.py
|
||||
pyinfra inventory.py setup-zfs-and-lxd.py
|
||||
```
|
||||
|
|
89
files/haproxy.cfg
Normal file
89
files/haproxy.cfg
Normal file
|
@ -0,0 +1,89 @@
|
|||
global
|
||||
log /dev/log local0
|
||||
log /dev/log local1 notice
|
||||
chroot /var/lib/haproxy
|
||||
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
|
||||
stats timeout 30s
|
||||
user haproxy
|
||||
group haproxy
|
||||
daemon
|
||||
|
||||
# Default SSL material locations
|
||||
ca-base /etc/ssl/certs
|
||||
crt-base /etc/ssl/private
|
||||
|
||||
ssl-default-bind-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-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
|
||||
ssl-default-bind-options prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
|
||||
ssl-default-server-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-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
|
||||
ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets
|
||||
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/haproxy/dhparam
|
||||
ssl-dh-param-file /etc/haproxy/dhparam
|
||||
|
||||
|
||||
defaults
|
||||
log global
|
||||
mode http
|
||||
option httplog
|
||||
option dontlognull
|
||||
timeout connect 5000
|
||||
timeout client 50000
|
||||
timeout server 50000
|
||||
errorfile 400 /etc/haproxy/errors/400.http
|
||||
errorfile 403 /etc/haproxy/errors/403.http
|
||||
errorfile 408 /etc/haproxy/errors/408.http
|
||||
errorfile 500 /etc/haproxy/errors/500.http
|
||||
errorfile 502 /etc/haproxy/errors/502.http
|
||||
errorfile 503 /etc/haproxy/errors/503.http
|
||||
errorfile 504 /etc/haproxy/errors/504.http
|
||||
|
||||
frontend gitea-ssh
|
||||
mode tcp
|
||||
bind :22
|
||||
bind :::22 v6only
|
||||
default_backend gitea-ssh
|
||||
|
||||
backend gitea-ssh
|
||||
mode tcp
|
||||
server gitea 127.0.0.1:2222 check send-proxy
|
||||
|
||||
frontend default
|
||||
|
||||
bind :80
|
||||
bind :::80 v6only
|
||||
bind :443 ssl crt /etc/ssl/haproxy/ strict-sni alpn h2,http/1.1
|
||||
bind :::443 v6only ssl crt /etc/ssl/haproxy/ strict-sni alpn h2,http/1.1
|
||||
|
||||
# HSTS (15768000 seconds = 6 months)
|
||||
http-response set-header Strict-Transport-Security max-age=15768000
|
||||
reqadd X-Forwarded-Proto:\ https if { ssl_fc }
|
||||
|
||||
# Let's Encrypt
|
||||
acl letsencrypt path_dir -i /.well-known/acme-challenge
|
||||
use_backend localhost if letsencrypt
|
||||
|
||||
# mo-f.fr
|
||||
acl mof hdr_end(host) -i mo-f.fr
|
||||
use_backend mof if mof
|
||||
|
||||
# play.benpro.fr
|
||||
acl play hdr(host) -i play.benpro.fr
|
||||
use_backend play if play
|
||||
|
||||
#default_backend localhost
|
||||
|
||||
backend localhost
|
||||
option forwardfor
|
||||
server localhost 127.0.0.1:8080 check send-proxy
|
||||
|
||||
backend mof
|
||||
# Benhind CloudFlare, X-Forwarded-For always setted, do not override
|
||||
option forwardfor if-none
|
||||
redirect scheme https if !{ ssl_fc }
|
||||
server mof 127.0.0.1:8081 check
|
||||
|
||||
backend play
|
||||
option forwardfor
|
||||
redirect scheme https if !{ ssl_fc }
|
||||
server play 127.0.0.1:8096 check
|
29
files/lxd.yml
Normal file
29
files/lxd.yml
Normal file
|
@ -0,0 +1,29 @@
|
|||
config: {}
|
||||
networks:
|
||||
- config:
|
||||
ipv4.address: auto
|
||||
ipv6.address: auto
|
||||
description: ""
|
||||
name: lxdbr0
|
||||
type: ""
|
||||
project: default
|
||||
storage_pools:
|
||||
- config:
|
||||
source: local
|
||||
description: ""
|
||||
name: default
|
||||
driver: zfs
|
||||
profiles:
|
||||
- config: {}
|
||||
description: ""
|
||||
devices:
|
||||
eth0:
|
||||
name: eth0
|
||||
network: lxdbr0
|
||||
type: nic
|
||||
root:
|
||||
path: /
|
||||
pool: default
|
||||
type: disk
|
||||
name: default
|
||||
cluster: null
|
53
files/nginx.default
Normal file
53
files/nginx.default
Normal file
|
@ -0,0 +1,53 @@
|
|||
server {
|
||||
listen 127.0.0.1:8080 default_server proxy_protocol;
|
||||
set_real_ip_from 127.0.0.1;
|
||||
real_ip_header proxy_protocol;
|
||||
|
||||
# SSL configuration
|
||||
#
|
||||
# listen 443 ssl default_server;
|
||||
# listen [::]:443 ssl default_server;
|
||||
#
|
||||
# Note: You should disable gzip for SSL traffic.
|
||||
# See: https://bugs.debian.org/773332
|
||||
#
|
||||
# Read up on ssl_ciphers to ensure a secure configuration.
|
||||
# See: https://bugs.debian.org/765782
|
||||
#
|
||||
# Self signed certs generated by the ssl-cert package
|
||||
# Don't use them in a production server!
|
||||
#
|
||||
# include snippets/snakeoil.conf;
|
||||
|
||||
root /var/www/html;
|
||||
|
||||
# Add index.php to the list if you are using PHP
|
||||
index index.html index.htm index.nginx-debian.html;
|
||||
|
||||
server_name _;
|
||||
|
||||
location / {
|
||||
# First attempt to serve request as file, then
|
||||
# as directory, then fall back to displaying a 404.
|
||||
try_files $uri $uri/ =404;
|
||||
}
|
||||
|
||||
# pass PHP scripts to FastCGI server
|
||||
#
|
||||
#location ~ \.php$ {
|
||||
# include snippets/fastcgi-php.conf;
|
||||
#
|
||||
# # With php-fpm (or other unix sockets):
|
||||
# fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
|
||||
# # With php-cgi (or other tcp sockets):
|
||||
# fastcgi_pass 127.0.0.1:9000;
|
||||
#}
|
||||
|
||||
# deny access to .htaccess files, if Apache's document root
|
||||
# concurs with nginx's one
|
||||
#
|
||||
#location ~ /\.ht {
|
||||
# deny all;
|
||||
#}
|
||||
}
|
||||
|
14
files/ondemand.service
Normal file
14
files/ondemand.service
Normal file
|
@ -0,0 +1,14 @@
|
|||
[Unit]
|
||||
Description=Set the CPU Frequency Scaling governor
|
||||
ConditionVirtualization=no
|
||||
ConditionPathExists=/sys/devices/system/cpu/online
|
||||
# Don't run if we're going to start an Android LXC container on Ubuntu Touch
|
||||
ConditionPathExists=!/etc/init/lxc-android-config.conf
|
||||
|
||||
[Service]
|
||||
Type=idle
|
||||
ExecStart=/lib/systemd/set-cpufreq-performance
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
|
38
files/set-cpufreq-performance
Normal file
38
files/set-cpufreq-performance
Normal file
|
@ -0,0 +1,38 @@
|
|||
#! /bin/sh
|
||||
# Set the CPU Frequency Scaling governor to "performance"/"powersave" where available
|
||||
set -eu
|
||||
|
||||
FIRSTCPU=`cut -f1 -d- /sys/devices/system/cpu/online`
|
||||
AVAILABLE="/sys/devices/system/cpu/cpu$FIRSTCPU/cpufreq/scaling_available_governors"
|
||||
DOWN_FACTOR="/sys/devices/system/cpu/cpufreq/performance/sampling_down_factor"
|
||||
|
||||
[ -f $AVAILABLE ] || exit 0
|
||||
|
||||
read governors < $AVAILABLE
|
||||
case $governors in
|
||||
*performance*)
|
||||
GOVERNOR="performance"
|
||||
case $(uname -m) in
|
||||
ppc64*)
|
||||
SAMPLING=100
|
||||
;;
|
||||
esac
|
||||
break
|
||||
;;
|
||||
*)
|
||||
exit 0
|
||||
;;
|
||||
esac
|
||||
|
||||
[ -n "${GOVERNOR:-}" ] || exit 0
|
||||
|
||||
echo "Setting $GOVERNOR scheduler for all CPUs"
|
||||
|
||||
for CPUFREQ in /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
|
||||
do
|
||||
[ -f $CPUFREQ ] || continue
|
||||
echo -n $GOVERNOR > $CPUFREQ
|
||||
done
|
||||
if [ -n "${SAMPLING:-}" ] && [ -f $DOWN_FACTOR ]; then
|
||||
echo -n $SAMPLING > $DOWN_FACTOR
|
||||
fi
|
0
group_data/all.py
Normal file
0
group_data/all.py
Normal file
1
inventory.py
Normal file
1
inventory.py
Normal file
|
@ -0,0 +1 @@
|
|||
my_hosts = ['lxd10.benpro.fr']
|
127
setup-base.py
Normal file
127
setup-base.py
Normal file
|
@ -0,0 +1,127 @@
|
|||
from pyinfra import host
|
||||
from pyinfra.operations import apt, server, files, systemd
|
||||
|
||||
SUDO = True
|
||||
|
||||
server.user(
|
||||
name='Add user benpro',
|
||||
user='benpro',
|
||||
groups=['sudo'],
|
||||
public_keys='ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFs7yO0auvwFL8HTLMUq6lET6DMYLhqhd32rqFfZUsjL openpgp:0xA32E99AD',
|
||||
shell='/bin/bash',
|
||||
present=True,
|
||||
)
|
||||
|
||||
server.hostname(
|
||||
name='Set the hostname',
|
||||
hostname='lxd10.benpro.fr',
|
||||
)
|
||||
|
||||
apt.update(
|
||||
name='Update apt repositories',
|
||||
)
|
||||
|
||||
apt.upgrade(
|
||||
name='Upgrade apt packages',
|
||||
)
|
||||
|
||||
apt.packages(
|
||||
name='Install ufw',
|
||||
packages=['ufw'],
|
||||
update=False,
|
||||
)
|
||||
|
||||
server.shell(
|
||||
name='Add ufw rules',
|
||||
commands=['ufw limit 22', 'ufw limit 28', 'ufw allow 80', 'ufw allow 443'],
|
||||
)
|
||||
|
||||
server.shell(
|
||||
name='Enable ufw',
|
||||
commands=['yes | ufw enable'],
|
||||
)
|
||||
|
||||
files.line(
|
||||
name='Set port 28 for SSH',
|
||||
path='/etc/ssh/sshd_config',
|
||||
line=r'Port .*',
|
||||
replace='Port 28',
|
||||
)
|
||||
|
||||
systemd.service(
|
||||
name='Reload sshd',
|
||||
service='ssh.service',
|
||||
reloaded=True,
|
||||
)
|
||||
|
||||
apt.packages(
|
||||
name='Install packages',
|
||||
packages=['zfsutils-linux', 'manpages', 'man', 'snapd', 'vim', 'file', 'parted', 'htop', 'ncdu', 'byobu', 'tcpdump', 'lm-sensors'],
|
||||
update=False,
|
||||
)
|
||||
|
||||
if not host.fact.directory('/var/snap/lxd'):
|
||||
server.shell(
|
||||
name='Install lxd',
|
||||
commands=['snap install lxd'],
|
||||
)
|
||||
|
||||
if not host.fact.command('file -s /dev/sdc1 | grep swap || true'):
|
||||
server.shell(
|
||||
name='Create swap',
|
||||
commands=['wipefs -a /dev/sdc1', 'mkswap /dev/sdc1'],
|
||||
)
|
||||
|
||||
files.line(
|
||||
name='Add swap to /etc/fstab',
|
||||
path='/etc/fstab',
|
||||
line='/dev/sdc1 none swap defaults 0 0',
|
||||
)
|
||||
|
||||
server.shell(
|
||||
name='Enable swap',
|
||||
commands=['swapon -a'],
|
||||
)
|
||||
|
||||
files.line(
|
||||
name='Disable intel_pstate',
|
||||
path='/etc/default/grub',
|
||||
line='GRUB_CMDLINE_LINUX="intel_pstate=disable"',
|
||||
)
|
||||
|
||||
server.shell(
|
||||
name='Reload grub',
|
||||
commands=['update-grub'],
|
||||
)
|
||||
|
||||
files.put(
|
||||
name='Install set-cpufreq-performance',
|
||||
src='files/set-cpufreq-performance',
|
||||
dest='/lib/systemd/set-cpufreq-performance',
|
||||
user='root',
|
||||
group='root',
|
||||
mode='755',
|
||||
)
|
||||
|
||||
files.put(
|
||||
name='Override systemd ondemand.service',
|
||||
src='files/ondemand.service',
|
||||
dest='/etc/systemd/system/ondemand.service',
|
||||
user='root',
|
||||
group='root',
|
||||
mode='644',
|
||||
)
|
||||
|
||||
systemd.daemon_reload(
|
||||
name='Reload systemd',
|
||||
user_mode=False,
|
||||
)
|
||||
|
||||
systemd.service(
|
||||
name='Restart and enable ondemand service',
|
||||
service='ondemand.service',
|
||||
running=True,
|
||||
restarted=True,
|
||||
enabled=True,
|
||||
)
|
||||
|
88
setup-haproxy.py
Normal file
88
setup-haproxy.py
Normal file
|
@ -0,0 +1,88 @@
|
|||
from pyinfra import host
|
||||
from pyinfra.operations import server, files, systemd, apt
|
||||
|
||||
SUDO = True
|
||||
|
||||
apt.packages(
|
||||
name='Install packages',
|
||||
packages=['certbot', 'haproxy', 'nginx'],
|
||||
update=False,
|
||||
)
|
||||
|
||||
files.put(
|
||||
name='Upload Nginx default vhost',
|
||||
src='files/nginx.default',
|
||||
dest='/etc/nginx/sites-available/default',
|
||||
user='root',
|
||||
group='root',
|
||||
mode='644',
|
||||
)
|
||||
|
||||
systemd.service(
|
||||
name='Restart and enable nginx service',
|
||||
service='nginx.service',
|
||||
running=True,
|
||||
restarted=True,
|
||||
enabled=True,
|
||||
)
|
||||
|
||||
files.put(
|
||||
name='Upload HAProxy config',
|
||||
src='files/haproxy.cfg',
|
||||
dest='/etc/haproxy/haproxy.cfg',
|
||||
user='root',
|
||||
group='root',
|
||||
mode='644',
|
||||
)
|
||||
|
||||
files.directory(
|
||||
name='Ensure /etc/ssl/haproxy exists',
|
||||
path='/etc/ssl/haproxy',
|
||||
user='root',
|
||||
group='root',
|
||||
mode=700
|
||||
)
|
||||
|
||||
if not host.fact.file('/etc/haproxy/dhparam'):
|
||||
server.shell(
|
||||
name='Generate dhparam',
|
||||
commands=['openssl dhparam 2048 > /etc/haproxy/dhparam']
|
||||
)
|
||||
|
||||
systemd.service(
|
||||
name='Restart and enable HAProxy service',
|
||||
service='haproxy.service',
|
||||
running=True,
|
||||
restarted=True,
|
||||
enabled=True,
|
||||
)
|
||||
|
||||
if not host.fact.directory('/etc/letsencrypt/live/mo-f.fr'):
|
||||
server.shell(
|
||||
name='Add certificate mo-f.fr',
|
||||
commands=['certbot certonly --non-interactive --email certbot@benpro.fr --agree-tos --webroot --webroot-path /var/www/html/ -d mo-f.fr -d download.mo-f.fr -d ipv4.mo-f.fr -d oppai.mo-f.fr -d static-uploads.mo-f.fr -d www.mo-f.fr'],
|
||||
)
|
||||
|
||||
if not host.fact.directory('/etc/letsencrypt/live/play.benpro.fr'):
|
||||
server.shell(
|
||||
name='Add certificate play.benpro.fr',
|
||||
commands=['certbot certonly --non-interactive --email certbot@benpro.fr --agree-tos --webroot --webroot-path /var/www/html/ -d play.benpro.fr'],
|
||||
)
|
||||
|
||||
if not host.fact.directory('/etc/letsencrypt/live/mo-f.fr'):
|
||||
server.shell(
|
||||
name='Add certificate mo-f.fr to HAProxy',
|
||||
commands=['cat /etc/letsencrypt/live/mo-f.fr/fullchain.pem /etc/letsencrypt/live/mo-f.fr/privkey.pem > /etc/ssl/haproxy/mo-f.fr.pem']
|
||||
)
|
||||
|
||||
if not host.fact.directory('/etc/letsencrypt/live/play.benpro.fr'):
|
||||
server.shell(
|
||||
name='Add certificate play.benpro.fr to HAProxy',
|
||||
commands=['cat /etc/letsencrypt/live/play.benpro.fr/fullchain.pem /etc/letsencrypt/live/play.benpro.fr/privkey.pem > /etc/ssl/haproxy/play.benpro.fr.pem']
|
||||
)
|
||||
|
||||
systemd.service(
|
||||
name='Reload HAProxy service',
|
||||
service='haproxy.service',
|
||||
reloaded=True,
|
||||
)
|
91
setup-zfs-and-lxd.py
Normal file
91
setup-zfs-and-lxd.py
Normal file
|
@ -0,0 +1,91 @@
|
|||
from pyinfra import host
|
||||
from pyinfra.operations import server, files
|
||||
|
||||
SUDO = True
|
||||
|
||||
# This suppose you have:
|
||||
# sda 8:0 0 2.7T 0 disk
|
||||
# ├─sda1 8:1 0 512M 0 part
|
||||
# │ └─md0 9:0 0 511M 0 raid1 /boot
|
||||
# ├─sda2 8:2 0 40G 0 part
|
||||
# │ └─md1 9:1 0 40G 0 raid1 /
|
||||
# └─sda3 8:3 0 1M 0 part
|
||||
# sdb 8:16 0 2.7T 0 disk
|
||||
# ├─sdb1 8:17 0 512M 0 part
|
||||
# │ └─md0 9:0 0 511M 0 raid1 /boot
|
||||
# ├─sdb2 8:18 0 40G 0 part
|
||||
# │ └─md1 9:1 0 40G 0 raid1 /
|
||||
# └─sdb3 8:19 0 1M 0 part
|
||||
# sdc 8:32 0 223.6G 0 disk
|
||||
# └─sdc1 8:33 0 24G 0 part
|
||||
|
||||
if not host.fact.command('lsblk | grep sda4 || true'):
|
||||
server.shell(
|
||||
name='Create sda4 for zpool',
|
||||
commands=['sgdisk -n4:0:0 -t4:BF00 /dev/sda', 'partprobe']
|
||||
)
|
||||
|
||||
if not host.fact.command('lsblk | grep sdb4 || true'):
|
||||
server.shell(
|
||||
name='Create sdb4 for zpool',
|
||||
commands=['sgdisk -n4:0:0 -t4:BF00 /dev/sdb', 'partprobe']
|
||||
)
|
||||
|
||||
if not host.fact.command('lsblk | grep sdc2 || true'):
|
||||
server.shell(
|
||||
name='Create sdc2 for ZFS cache L2ARC',
|
||||
commands=['sgdisk -n2:0:0 -t2:FD00 /dev/sdc', 'partprobe']
|
||||
)
|
||||
|
||||
# zfs.key is not stored on GIT, but on KeePassXC
|
||||
# When using new server be sure to set right disk ID
|
||||
if not host.fact.command('zpool list local | grep local || true'):
|
||||
server.shell(
|
||||
name='Create ZFS pool',
|
||||
commands=['zpool create -o ashift=12 -o autotrim=on -O encryption=aes-256-gcm -O keylocation=file:///etc/zfs.key -O keyformat=passphrase -O acltype=posixacl -O canmount=off -O dedup=on -O compression=lz4 -O dnodesize=auto -O normalization=formD -O relatime=on -O xattr=sa local mirror /dev/disk/by-id/ata-ST33000650NS_Z290FDG2-part4 /dev/disk/by-id/ata-ST33000650NS_Z290FEJQ-part4 cache /dev/disk/by-id/ata-INTEL_SSDSC2CW240A3_CVCV306301L3240CGN-part2']
|
||||
)
|
||||
|
||||
files.put(
|
||||
name='Upload LXD config',
|
||||
src='files/lxd.yml',
|
||||
dest='/tmp/lxd.yml',
|
||||
mode='644',
|
||||
)
|
||||
|
||||
if not host.fact.command('lxc storage list | grep local || true'):
|
||||
server.shell(
|
||||
name='Init LXD',
|
||||
commands=['cat /tmp/lxd.yml | lxd init --preseed']
|
||||
)
|
||||
|
||||
if not host.fact.command('lxc storage volume list default | grep backups || true'):
|
||||
server.shell(
|
||||
name='Set LXD backups volumes',
|
||||
commands=['lxc storage volume create default backups', 'lxc config set storage.backups_volume default/backups']
|
||||
)
|
||||
|
||||
if not host.fact.command('lxc storage volume list default | grep images || true'):
|
||||
server.shell(
|
||||
name='Set LXD images volumes',
|
||||
commands=['lxc storage volume create default images', 'lxc config set storage.images_volume default/images']
|
||||
)
|
||||
|
||||
files.directory(
|
||||
name='Ensure /var/backups/lxd exists',
|
||||
path='/var/backups/lxd',
|
||||
user='root',
|
||||
group='root',
|
||||
mode=700
|
||||
)
|
||||
|
||||
if not host.fact.command('zfs list | grep exports || true'):
|
||||
server.shell(
|
||||
name='Create ZFS volume exports',
|
||||
commands=['zfs create local/exports -o mountpoint=/var/backups/lxd']
|
||||
)
|
||||
|
||||
files.line(
|
||||
name='Add info to motd',
|
||||
path='/etc/motd',
|
||||
line='`zfs load-key -a && systemctl start snap.lxd.daemon.service',
|
||||
)
|
Reference in a new issue