Compare commits
2 commits
5ba1a70ff2
...
369bdc1838
Author | SHA1 | Date | |
---|---|---|---|
369bdc1838 | |||
bca1119fd4 |
6 changed files with 122 additions and 55 deletions
100
manage.py
100
manage.py
|
@ -14,15 +14,14 @@ def backupProj(project):
|
|||
|
||||
|
||||
def getImageId (image):
|
||||
return subprocess.run(["podman", "image", "inspect", "--format", "{{.Id}}", image], capture_output=True, text=True).stdout.strip()
|
||||
return runPodman("image", ["inspect", "--format", "{{.Id}}", image]).stdout.strip()
|
||||
|
||||
|
||||
def getUid(service):
|
||||
if service in env['users'].keys():
|
||||
user = env['users'][service] + env['uid_shift']
|
||||
return env['users'][service] + env['uid_shift']
|
||||
else:
|
||||
user = 1000
|
||||
return user
|
||||
return env['podman_uid']
|
||||
|
||||
|
||||
def pullProj(project):
|
||||
|
@ -34,7 +33,7 @@ def pullProj(project):
|
|||
pulledImages = []
|
||||
for image in images:
|
||||
currentId = getImageId(image)
|
||||
subprocess.run(["podman", "pull", image])
|
||||
runPodman("pull", image)
|
||||
pulledId = getImageId(image)
|
||||
if currentId != pulledId:
|
||||
pulledImages += image
|
||||
|
@ -57,17 +56,50 @@ def renderFile(templateFile):
|
|||
outputFile.close()
|
||||
|
||||
|
||||
def runPodman(cmd, args):
|
||||
if isinstance(args, str):
|
||||
args = args.split(' ')
|
||||
|
||||
if cmd == 'compose':
|
||||
runArgs = ["podman-compose"] + args
|
||||
else:
|
||||
runArgs = ["podman", cmd] + args
|
||||
|
||||
if env['rootless']:
|
||||
return subprocess.run(runArgs, capture_output=True, text=True)
|
||||
else:
|
||||
return runSudo(runArgs)
|
||||
|
||||
|
||||
def runSudo(args):
|
||||
if isinstance(args, str):
|
||||
args = args.split(' ')
|
||||
|
||||
child = subprocess.Popen(["sudo"] + args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
|
||||
if re.search('^\\[sudo\\] password for .+', child.stdout.read().strip()):
|
||||
child.communicate(input=input().encode())[0]
|
||||
|
||||
child.wait()
|
||||
|
||||
stderr = child.stderr.read().strip()
|
||||
if stderr != '':
|
||||
print(stderr, file=sys.stderr)
|
||||
|
||||
return child
|
||||
|
||||
|
||||
def setCertPerms(service):
|
||||
for path in ["/etc/letsencrypt", "/etc/letsencrypt/live", "/etc/letsencrypt/archive"]:
|
||||
setOwner(path, 0, 0)
|
||||
setPerms(path, 751)
|
||||
dirs = ["/etc/letsencrypt", "/etc/letsencrypt/live", "/etc/letsencrypt/archive"]
|
||||
|
||||
pkeyFile = env['certs'][service]['pkey']
|
||||
|
||||
|
||||
domain_dir = re.search('.+(?=\\/.+$)', pkeyFile).group(0)
|
||||
for path in [domain_dir, re.sub('live', 'archive', domain_dir)]:
|
||||
setOwner(path, env['host_uid'], getUid(service))
|
||||
setPerms(path, 550)
|
||||
dirs += [domain_dir, re.sub('live', 'archive', domain_dir)]
|
||||
|
||||
for path in dirs:
|
||||
setOwner(path, 0, env['podman_uid'])
|
||||
setPerms(path, 711)
|
||||
|
||||
setOwner(pkeyFile, 0, getUid(service))
|
||||
setPerms(pkeyFile, 640)
|
||||
|
@ -77,8 +109,8 @@ def setNftables():
|
|||
renderFile("nftables.conf.mako")
|
||||
if not filecmp.cmp("nftables.conf.rendered", "/etc/nftables.conf"):
|
||||
print("nftables.conf changed, copying new version.")
|
||||
sudoRun(["cp", "nftables.conf.rendered", "/etc/nftables.conf"])
|
||||
sudoRun(["systemctl", "restart", "nftables"])
|
||||
runSudo(["cp", "nftables.conf.rendered", "/etc/nftables.conf"])
|
||||
runSudo(["systemctl", "restart", "nftables"])
|
||||
else:
|
||||
print("nftables.conf unchanged.")
|
||||
|
||||
|
@ -92,7 +124,7 @@ def setOwner(path, uid=None, gid=None):
|
|||
|
||||
if stat.st_uid != uid or stat.st_gid != gid:
|
||||
print(f"Changing ownership of {path} to {uid}:{gid} from {stat.st_uid}:{stat.st_gid}.")
|
||||
sudoRun(["chown", f"{uid}:{gid}", path])
|
||||
runSudo(["chown", f"{uid}:{gid}", path])
|
||||
else:
|
||||
print(f"Ownership of {path} already set to {uid}:{gid}.")
|
||||
|
||||
|
@ -103,10 +135,10 @@ def setPerms(path, mode):
|
|||
curMode = oct(stat.st_mode)[-3:]
|
||||
if mode != curMode:
|
||||
print(f"Changing permissions of {path} to {mode} from {curMode}.")
|
||||
if stat.st_uid == env['host_uid']:
|
||||
if stat.st_uid == os.getuid():
|
||||
subprocess.run(["chmod", mode, path])
|
||||
else:
|
||||
subprocess.run(["sudo", "chmod", mode, path])
|
||||
runSudo(["chmod", mode, path])
|
||||
else:
|
||||
print(f"Permissions of {path} already set to {mode}.")
|
||||
|
||||
|
@ -116,6 +148,15 @@ def setupProj(project):
|
|||
|
||||
backupProj(project)
|
||||
|
||||
if project == 'diun':
|
||||
if not os.path.isfile(env['socket']):
|
||||
if env['rootless']:
|
||||
subprocess.run(["systemctl", "--user", "restart", "podman.socket"])
|
||||
else:
|
||||
runSudo("systemctl restart podman.socket")
|
||||
setPerms(env['socket'], 660)
|
||||
setOwner(env['socket'], env['podman_uid'], getUid('diun'))
|
||||
|
||||
if project in env['certs'].keys():
|
||||
setCertPerms(project)
|
||||
|
||||
|
@ -123,22 +164,18 @@ def setupProj(project):
|
|||
renderFile(templateFile)
|
||||
renderedFilename = re.sub('\\.mako$', '.rendered', templateFile)
|
||||
setPerms(renderedFilename, 640)
|
||||
setOwner(renderedFilename, env['host_uid'], getUid(project))
|
||||
setOwner(renderedFilename, os.getuid(), getUid(project))
|
||||
|
||||
upProj(project)
|
||||
|
||||
|
||||
def sudoRun(args):
|
||||
child = subprocess.Popen(["sudo"] + args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||
if re.search('^\\[sudo\\] password for .+', child.stdout.read().strip()):
|
||||
child.communicate(input=input().encode())[0]
|
||||
|
||||
|
||||
def upProj(project):
|
||||
if runPodman("container", ["exists", project]).returncode == 0:
|
||||
print(f"Tearing down stack for project {project}.")
|
||||
runPodman("compose", ["-f", f"projects/{project}/compose.yaml.rendered", "down"])
|
||||
|
||||
print(f"Creating & starting stack for project {project}.")
|
||||
if subprocess.run(["podman", "container", "exists", project]).returncode == 0:
|
||||
subprocess.run(["podman-compose", "-f", f"projects/{project}/compose.yaml.rendered", "down"])
|
||||
subprocess.run(["podman-compose", "-f", f"projects/{project}/compose.yaml.rendered", "up", "-d"])
|
||||
runPodman("compose", ["-f", f"projects/{project}/compose.yaml.rendered", "up", "-d"])
|
||||
|
||||
|
||||
def updateProj(project):
|
||||
|
@ -160,13 +197,14 @@ def main():
|
|||
|
||||
with open(envFile, 'r') as envfile, open(secretsFile, 'r') as secretsfile:
|
||||
global env, secrets
|
||||
env = yaml.safe_load(envfile)
|
||||
env = yaml.safe_load(Template(filename=envFile).render(env=env))
|
||||
env = yaml.safe_load(Template(filename=envFile).render())
|
||||
secrets = yaml.safe_load(secretsfile)
|
||||
|
||||
setOwner(secretsFile, env['host_uid'], env['host_uid'])
|
||||
|
||||
setOwner(secretsFile, os.getuid(), os.getgid())
|
||||
setPerms(secretsFile, 600)
|
||||
|
||||
print("\nUsing socket " + env['socket'] + ".")
|
||||
|
||||
print("\nChoose action:")
|
||||
print("[1/S] Setup project")
|
||||
print("[2/U] Update project")
|
||||
|
|
|
@ -2,7 +2,6 @@ services:
|
|||
coturn:
|
||||
container_name: coturn
|
||||
image: docker.io/coturn/coturn:4-alpine
|
||||
network_mode: pasta
|
||||
restart: always
|
||||
user: ${env['users']['coturn']}:${env['users']['coturn']}
|
||||
ports:
|
||||
|
@ -18,3 +17,4 @@ services:
|
|||
- ${env['certs']['coturn']['cert']}:/etc/coturn/cert.pem:ro
|
||||
- ${env['certs']['coturn']['pkey']}:/etc/coturn/pkey.pem:ro
|
||||
|
||||
${env['networks_attr']}
|
||||
|
|
|
@ -2,8 +2,8 @@ services:
|
|||
diun:
|
||||
container_name: diun
|
||||
image: docker.io/crazymax/diun:4
|
||||
network_mode: pasta
|
||||
restart: always
|
||||
user: ${env['users']['diun']}:${env['users']['diun']}
|
||||
command: serve
|
||||
env_file: .env.rendered
|
||||
volumes:
|
||||
|
@ -11,5 +11,7 @@ services:
|
|||
- ./images.yml:/etc/diun/images.yml:ro
|
||||
- data:/data
|
||||
|
||||
${env['networks_attr']}
|
||||
|
||||
volumes:
|
||||
data:
|
||||
|
|
|
@ -2,7 +2,6 @@ services:
|
|||
homepage:
|
||||
container_name: homepage
|
||||
image: git.ahur.ac/viyurz/homepage:latest
|
||||
network_mode: pasta
|
||||
restart: always
|
||||
user: ${env['users']['homepage']}:${env['users']['homepage']}
|
||||
ports:
|
||||
|
|
40
pyenv.yml
40
pyenv.yml
|
@ -1,10 +1,23 @@
|
|||
domain: viyurz.fr
|
||||
timezone: "Europe/Paris"
|
||||
host_uid: 1000
|
||||
socket: "/run/user/${env['host_uid']}/podman/podman.sock"
|
||||
|
||||
# UID shift for mapping between host & containers
|
||||
uid_shift: 99999
|
||||
<%!
|
||||
import os, subprocess
|
||||
|
||||
uid = os.getuid()
|
||||
rootless = os.path.exists(f"/run/user/{uid}/podman/podman.sock")
|
||||
%>
|
||||
% if rootless:
|
||||
rootless: true
|
||||
podman_uid: ${uid}
|
||||
uid_shift: ${int(subprocess.run(['sh', '-c', "grep " + os.getlogin() + " /etc/subuid | cut -d ':' -f 2"], capture_output=True, text=True).stdout.strip()) - 1}
|
||||
socket: "/run/user/${uid}/podman/podman.sock"
|
||||
% else:
|
||||
rootless: false
|
||||
podman_uid: 0
|
||||
uid_shift: 0
|
||||
socket: "/run/podman/podman.sock"
|
||||
% endif
|
||||
|
||||
|
||||
# cifs_credentials is undefined when we run the backup playbook
|
||||
|
@ -43,17 +56,23 @@ cifs_mounts:
|
|||
dir_mode: 750
|
||||
|
||||
|
||||
borg_repodir: "${env['cifs_mounts']['backups']['path']}/borg"
|
||||
borg_repodir: "{env['cifs_mounts']['backups']['path']}/borg"
|
||||
borg_passphrase_file: /etc/borg-passphrase.txt
|
||||
|
||||
|
||||
certs:
|
||||
coturn:
|
||||
cert: "/etc/letsencrypt/live/turn.${env['domain']}/fullchain.pem"
|
||||
pkey: "/etc/letsencrypt/live/turn.${env['domain']}/privkey.pem"
|
||||
cert: "/etc/letsencrypt/live/turn.viyurz.fr/fullchain.pem"
|
||||
pkey: "/etc/letsencrypt/live/turn.viyurz.fr/privkey.pem"
|
||||
mailserver:
|
||||
cert: "/etc/letsencrypt/live/mail.${env['domain']}/fullchain.pem"
|
||||
pkey: "/etc/letsencrypt/live/mail.${env['domain']}/privkey.pem"
|
||||
cert: "/etc/letsencrypt/live/mail.viyurz.fr/fullchain.pem"
|
||||
pkey: "/etc/letsencrypt/live/mail.viyurz.fr/privkey.pem"
|
||||
|
||||
|
||||
networks_attr: |
|
||||
networks:
|
||||
default:
|
||||
enable_ipv6: true
|
||||
|
||||
|
||||
# Ports exposed to host
|
||||
|
@ -89,6 +108,7 @@ ports:
|
|||
# UID in containers
|
||||
users:
|
||||
coturn: 666
|
||||
diun: 1011
|
||||
etebase: 373
|
||||
fireshare: 1007
|
||||
hedgedoc: 1004
|
||||
|
@ -118,6 +138,6 @@ volumes:
|
|||
stump_configdir: /mnt/stump/config
|
||||
stump_datadir: /mnt/stump/data
|
||||
synapse_datadir: /mnt/synapsedata
|
||||
syncthing_datadir: "${env['cifs_mounts']['syncthing']['path']}"
|
||||
syncthing_datadir: "{env['cifs_mounts']['syncthing']['path']}"
|
||||
uptime_kuma_datadir: /mnt/uptimekumadata
|
||||
vaultwarden_datadir: /mnt/vwdata
|
||||
|
|
30
setup.sh
30
setup.sh
|
@ -6,15 +6,27 @@ if [[ $(whoami) == "root" ]]; then
|
|||
fi
|
||||
|
||||
|
||||
sudo apt install -y aardvark-dns dbus-user-session nftables passt podman podman-compose python3-mako uidmap
|
||||
|
||||
|
||||
for unit in podman.service podman.socket podman-auto-update.service podman-auto-update.timer podman-clean-transient.service podman-restart.service; do
|
||||
sudo systemctl disable --now "$unit"
|
||||
while ! [[ "$podman_mode" =~ ^(rootful|rootless)$ ]]; do
|
||||
read -rp "Rootful or rootless Podman? " podman_mode
|
||||
done
|
||||
|
||||
|
||||
sudo loginctl enable-linger $USER
|
||||
declare -a podman_units=(podman.service podman.socket podman-auto-update.service podman-auto-update.timer podman-clean-transient.service podman-restart.service)
|
||||
|
||||
|
||||
if [[ "$podman_mode" == "rootless" ]]; then
|
||||
sudo apt install -y aardvark-dns dbus-user-session nftables passt podman podman-compose python3-mako uidmap
|
||||
|
||||
sudo loginctl enable-linger "$USER"
|
||||
|
||||
sudo systemctl disable --now "${podman_units[@]}"
|
||||
systemctl --user enable --now "${podman_units[@]}"
|
||||
else
|
||||
sudo apt install -y aardvark-dns nftables podman podman-compose python3-mako
|
||||
|
||||
systemctl --user disable --now "${podman_units[@]}"
|
||||
sudo systemctl enable --now "${podman_units[@]}"
|
||||
fi
|
||||
|
||||
|
||||
declare -A sysctl_vars=(
|
||||
|
@ -27,12 +39,8 @@ echo -n "" | sudo tee /etc/sysctl.d/podman.conf
|
|||
for key in "${!sysctl_vars[@]}"; do
|
||||
value="${sysctl_vars[$key]}"
|
||||
echo "$key = $value" | sudo tee -a /etc/sysctl.d/podman.conf
|
||||
sudo sysctl -p
|
||||
done
|
||||
sudo sysctl -p
|
||||
|
||||
|
||||
for unit in podman.service podman.socket podman-restart.service; do
|
||||
systemctl --user enable --now "$unit"
|
||||
done
|
||||
|
||||
sudo systemctl enable --now nftables
|
||||
|
|
Loading…
Reference in a new issue