Compare commits

..

No commits in common. "35ae6515aaf0b7d734178e3da6896e59e92f9dac" and "83c4b18dbe8ed6b954cca6fbfce1d0f9ea8b314f" have entirely different histories.

18 changed files with 156 additions and 223 deletions

View file

@ -31,12 +31,10 @@ in
jellyfin.enable = mkEnableOption "Jellyfin media server";
minecraft.enable = mkEnableOption "Minecraft server";
nextcloud.enable = mkEnableOption "Nextcloud server";
ryot.enable = mkEnableOption "ryot server";
teamspeak.enable = mkEnableOption "TeamSpeak server";
terraria.enable = mkEnableOption "Terraria server";
trackmania.enable = mkEnableOption "TrackMania server";
vaultwarden.enable = mkEnableOption "Vaultwarden server";
wekan.enable = mkEnableOption "Wekan server";
woodpecker.enable = mkEnableOption "Woodpecker CI server";
};
};

View file

@ -62,12 +62,10 @@ in {
jellyfin.enable = true;
minecraft.enable = true;
nextcloud.enable = true;
ryot.enable = true;
teamspeak.enable = true;
terraria.enable = true;
trackmania.enable = true;
vaultwarden.enable = true;
wekan.enable = true;
woodpecker.enable = true;
};
};

View file

@ -5,7 +5,6 @@ begin
function installValhallaDeps -V dir
source "$dir/../lib/software.fish"
and pacinst fish git jq nix sudo tmux
sudo systemctl enable --now nix-daemon
end
function getDeploymentScript -V dir
@ -17,6 +16,7 @@ begin
waitNetwork
or exit
sudo systemctl enable --now nix-daemon
and source "$dir/../lib/software.fish"
and source "$dir/../Software/base-devel/main.fish"
and source "$dir/../Software/pacman/main.fish"

View file

@ -16,21 +16,19 @@ function backupAction -V dir
if [ -z "$VALHALLA_BACKUP_DIR" ]
if fish "$dir/../../../lib/modules/partition/confirm.fish" "Do you wish to store the backup on an SSH server?" n
set -l keyVar VALHALLA_BACKUP_SERVER_KEY
set -l keyPath ~root/.config/port-valhalla/valhalla
read -xP "Please specify the host name of the SSH server: " VALHALLA_BACKUP_SERVER
read -xP "Please specify the port of the SSH server (default 22): " VALHALLA_BACKUP_SERVER_PORT
read -xP "Please specify the name of the user to log in to the SSH server: " VALHALLA_BACKUP_SERVER_USER
if [ -z "$$keyVar" ]
set -gx "$keyVar" "$keyPath"
ssh-keygen -f "$$keyVar" -N ""
end
read -xP "Please specify the path to the key file for logging in to the SSH server: " VALHALLA_BACKUP_SERVER_KEY
if [ -z "$VALHALLA_BACKUP_SERVER_PORT" ]
set -x VALHALLA_BACKUP_SERVER_PORT 22
end
if [ -n "$VALHALLA_BACKUP_SERVER_USER" ]
set -x VALHALLA_BACKUP_SERVER "$VALHALLA_BACKUP_SERVER_USER@$VALHALLA_BACKUP_SERVER"
end
echo
echo "$(tput setaf 3)==== WARNING ====$(tput sgr0)"
echo "For a seamless experience, please make sure that you are able to establish an unattended ssh connection using key authentication."

View file

@ -32,7 +32,7 @@ services:
MARIADB_RANDOM_ROOT_PASSWORD: "yes"
MARIADB_AUTO_UPGRADE: "yes"
volumes:
- ./data/db:/var/lib/mysql
- ./database:/var/lib/mysql
command:
- --character-set-server=utf8mb4
- --collation-server=utf8mb4_unicode_ci

View file

@ -70,8 +70,8 @@ begin
yq "$envKey.USER_GID = $gid" |
sudo tee "$config" >/dev/null
sudo mkdir -p "$dir"
and sudo chown -R $uid:$gid "$dir"
mkdir -p "$dir"
and chown -R $uid:$gid "$dir"
rm "$file"
set port (yq (getSSHPortKey) "$overrides" | extractPort)

View file

@ -5,9 +5,9 @@ services:
user: 1337:1337
hostname: Jellyfin
volumes:
- ./data/config/jellyfin:/config
- ./config/jellyfin:/config
- cache:/cache
- ./data/media:/media
- ./media:/media
radarr:
image: linuxserver/radarr
restart: unless-stopped
@ -16,9 +16,9 @@ services:
PGID: 1337
volumes:
- /etc/localtime:/etc/localtime:ro
- ./data/config/radarr:/config
- ./data/media/movies:/movies
- ./data/downloads:/downloads
- ./config/radarr:/config
- ./media/movies:/movies
- ./downloads:/downloads
sonarr:
image: linuxserver/sonarr
restart: unless-stopped
@ -27,9 +27,9 @@ services:
PGID: 1337
volumes:
- /etc/localtime:/etc/localtime:ro
- ./data/config/sonarr:/config
- ./data/media/series:/tv
- ./data/downloads:/downloads
- ./config/sonarr:/config
- ./media/series:/tv
- ./downloads:/downloads
lidarr:
image: linuxserver/lidarr
restart: unless-stopped
@ -38,9 +38,9 @@ services:
PGID: 1337
volumes:
- /etc/localtime:/etc/localtime:ro
- ./data/config/lidarr:/config
- ./data/media/music:/music
- ./data/downloads:/downloads
- ./config/lidarr:/config
- ./media/music:/music
- ./downloads:/downloads
prowlarr:
image: linuxserver/prowlarr
restart: unless-stopped
@ -49,7 +49,7 @@ services:
PGID: 1337
volumes:
- /etc/localtime:/etc/localtime:ro
- ./data/config/prowlarr:/config
- ./config/prowlarr:/config
flaresolverr:
image: flaresolverr/flaresolverr
restart: unless-stopped
@ -58,11 +58,7 @@ services:
LOG_HTML: "false"
CAPTCHA_SOLVER: none
privoxy:
build:
context: .
dockerfile_inline: |
FROM walt3rl/proton-privoxy
RUN apk --update add ip6tables
image: walt3rl/proton-privoxy
restart: unless-stopped
volumes:
- /etc/localtime:/etc/localtime:ro
@ -79,9 +75,9 @@ services:
--allowedpath /downloads
--rtsocket /rtorrent/.local/share/rtorrent/rtorrent.sock
volumes:
- ./data/config/flood:/flood
- ./data/downloads:/downloads
- rtorrent:/rtorrent
- ./config/flood:/flood
- ./downloads:/downloads
- ./config/rtorrent:/rtorrent
rtorrent:
build:
dockerfile: ./rtorrent.Dockerfile
@ -100,8 +96,8 @@ services:
-o 'method.set=group.seeding.ratio.command, "d.cloase = ; d.erase = "'
volumes:
- /etc/localtime:/etc/localtime:ro
- rtorrent:/config
- ./data/downloads:/downloads
- ./config/rtorrent:/config
- ./downloads:/downloads
- ./data/proton:/proton
devices:
- /dev/net/tun
@ -139,4 +135,3 @@ services:
volumes:
cache: {}
rtorrent: {}

View file

@ -66,7 +66,7 @@ begin
URL="https://$(getServiceDomain "$domain" "")/" yq "$(getServiceKey "$service").environment.JELLYFIN_PublishedServerUrl = env(URL)" "$file" |
sudo tee "$overrides" >/dev/null
for dir in "$root"/data/{downloads,config/{,jellyfin,flood,radarr,sonarr,lidarr,prowlarr},media/{,movies,series,music}}
for dir in "$root"/{downloads,config/{,jellyfin,flood,rtorrent,radarr,sonarr,lidarr,prowlarr},media/{,movies,series,music}}
sudo mkdir -p "$dir"
and chown -R $uid:$gid "$dir"
end
@ -91,9 +91,9 @@ begin
printf "%s\0" \
"$_flag_name" / (
for app in $servarr
printf "%s\n" "$app" "/$app" ""
printf "%s\n" "$app" "/$app"
end) \
flood "/flood/"
flood "~ ^/flood.*"
end
function getServiceLocationConfig -a domain s location -V service -V flood

View file

@ -1,36 +1,25 @@
from argparse import ArgumentParser
from os import chmod, environ
from os import environ
from os.path import dirname
from random import choice
from re import M
import shlex
import subprocess
import sys
from protonvpn_cli import connection
from protonvpn_cli.constants import PASSFILE
from protonvpn_cli.utils import check_init, get_fastest_server, get_servers, set_config_value, pull_server_data
from protonvpn_cli.cli import FeatureEnum, protonvpn
def run_proton(args):
exit(
subprocess.run(
["proton"],
["pipenv", "run", "proton"],
cwd="/app",
env=dict(
environ,
PIPENV_VENV_IN_PROJECT=f"{1}",
PVPN_CMD_ARGS=" ".join(args))).returncode)
environ["PVPN_USERNAME"] = environ["PVPN_USERNAME"] + (environ["PVPN_TAGS"] or "")
with open(PASSFILE, "w") as f:
f.write("{0}\n{1}".format(environ["PVPN_USERNAME"], environ["PVPN_PASSWORD"]))
chmod(PASSFILE, 0o600)
check_init()
set_config_value("USER", "username", environ["PVPN_USERNAME"])
set_config_value("USER", "tier", environ["PVPN_TIER"])
set_config_value("USER", "default_protocol", environ["PVPN_PROTOCOL"])
set_config_value("USER", "initialized", 1)
protonvpn.ensure_connectivity()
args = sys.argv[1:]
@ -40,7 +29,7 @@ if not args:
parser = ArgumentParser(exit_on_error=False)
subParsers = parser.add_subparsers(dest="command")
initParser = subParsers.add_parser("init", aliases=["i"])
initParser = subParsers.add_parser("init", alias=["i"])
connectParser = subParsers.add_parser("connect", aliases=["c"])
for aliases in [
@ -61,38 +50,54 @@ try:
except:
pass
if parsedArgs is not None and parsedArgs.command == "init":
userName = input("Enter your Proton VPN username or email: ")
subprocess.run(["protonvpn-cli", "login", userName])
else:
session = protonvpn.get_session()
try:
session.ensure_valid()
except:
raise Exception(
"Your current session is invalid. Please initialize the session using the `init` subcommand.")
environ["PVPN_USERNAME"] = session.vpn_username + \
(environ.get("PVPN_TAGS") or "")
environ["PVPN_PASSWORD"] = session.vpn_password
environ["PVPN_TIER"] = f"{session.vpn_tier}"
if parsedArgs is not None and (
len(
list(
filter(
lambda item: item[1] not in [False, None],
vars(parsedArgs).items()))) > 1):
country = protonvpn.get_country()
def match(server):
features = list()
if parsedArgs.streaming:
pass
features.append(FeatureEnum.STREAMING)
if parsedArgs.sc:
pass
features.append(FeatureEnum.SECURE_CORE)
if parsedArgs.p2p:
pass
features.append(FeatureEnum.P2P)
if parsedArgs.tor:
pass
features.append(FeatureEnum.TOR)
return (parsedArgs.cc is None or server.exit_country.lower() == parsedArgs.cc.lower()) and (
all(feature in server.features for feature in features))
pull_server_data(force=True)
servers = list(filter(lambda server: match(server), get_servers()))
servers = session.servers.filter(match)
if len(servers) > 0:
if parsedArgs.fastest or not parsedArgs.random:
server = get_fastest_server(servers)
server = servers.get_fastest_server()
else:
server = choice(servers)
server = servers.get_random_server()
run_proton(["connect", server["Name"]])
run_proton(["connect", server.name])
else:
raise Exception(
f"Unable to find a server matching the specified criteria {args[1:]}!")

View file

@ -5,13 +5,8 @@ FROM debian
ARG PVPN_CLI_VER=2.2.12
ARG USERNAME=proton
ENV PVPN_USERNAME= \
PVPN_USERNAME_FILE= \
PVPN_PASSWORD= \
PVPN_PASSWORD_FILE= \
PVPN_TIER=2 \
ENV PVPN_TAGS="+pmp" \
PVPN_PROTOCOL=udp \
PVPN_TAGS="+pmp" \
PVPN_CMD_ARGS="connect --p2p --random" \
PVPN_DEBUG= \
HOST_NETWORK= \
@ -25,28 +20,9 @@ ENV PVPN_USERNAME= \
WORKDIR /root
COPY --from=rtorrent / /
RUN apt-get update -y \
&& apt-get upgrade -y \
&& apt-get install -y \
git \
iproute2 \
iptables \
natpmpc \
openvpn \
pipenv \
procps \
python3 \
python3-pip \
python3-setuptools \
sudo \
&& rm -rf /var/lib/apt/lists
RUN pip3 install --break-system-packages git+https://github.com/Rafficer/linux-cli-community.git@v$PVPN_CLI_VER#egg=protonvpn-cli
RUN mkdir /app
COPY --from=proton /root/.pvpn-cli /root/.pvpn-cli
COPY --from=proton /app/proton-privoxy/run /app/proton
COPY --from=proton /root/.pvpn-cli/pvpn-cli.cfg.clean /root/.pvpn-cli/pvpn-cli.cfg
RUN \
sed -i \
@ -56,7 +32,43 @@ RUN \
&& install -t /usr/local/bin /app/proton \
&& rm /app/proton
RUN apt-get update -y \
&& apt-get upgrade -y \
&& apt-get install -y \
curl \
gnupg \
&& curl https://repo.protonvpn.com/debian/dists/stable/main/binary-all/protonvpn-stable-release_1.0.3-3_all.deb -o proton.deb \
&& dpkg --install proton.deb \
&& apt-get remove -y \
curl \
&& apt-get update -y \
&& apt-get install -y protonvpn-cli \
&& rm -rf /var/lib/apt/lists
RUN apt-get update -y \
&& apt-get upgrade -y \
&& apt-get install -y \
git \
iproute2 \
iptables \
natpmpc \
pipenv \
python3-setuptools \
sudo \
&& rm -rf /var/lib/apt/lists
RUN \
cd /app \
&& PIPENV_VENV_IN_PROJECT=1 pipenv install git+https://github.com/Rafficer/linux-cli-community.git@v$PVPN_CLI_VER#egg=protonvpn-cli
RUN printf "%s\n" \
"#!/usr/bin/env -S dbus-run-session -- bash" \
"mkdir -p /proton/{keyrings,protonvpn}" \
"mkdir -p ~/.local/share" \
"mkdir -p ~/.config" \
"ln -Ts /proton/keyrings ~/.local/share/keyrings >/dev/null 2>&1" \
"ln -Ts /proton/protonvpn ~/.config/protonvpn >/dev/null 2>&1" \
"eval \"\$(echo -n 'root' | gnome-keyring-daemon --unlock)\"" \
"python3 /app/pvpn-cli.py \"\$@\"" > ./pvpn-cli \
&& install -Dm 755 ./pvpn-cli /usr/local/bin \
&& rm ./pvpn-cli
@ -65,20 +77,7 @@ RUN printf "%s\n" \
"#!/bin/bash" \
"groupadd --gid \$PGID ${USERNAME} > /dev/null" \
"useradd --create-home --home-dir \$PHOME ${USERNAME} --uid \$PUID -g ${USERNAME} 2>/dev/null" \
"chown ${USERNAME} \$PHOME" \
'[ ! -z "$1" ] && [ "$1" = "init" ] && export PVPN_CMD_ARGS="$@"' \
'if [ -z "$PVPN_USERNAME" ] && [ -z "$PVPN_USERNAME_FILE" ]; then' \
" echo 'Error: Either env var \$PVPN_USERNAME or \$PVPN_USERNAME_FILE is required.'" \
"exit 1" \
"fi" \
"" \
'if [ -z "$PVPN_PASSWORD" ] && [ -z "$PVPN_PASSWORD_FILE" ]; then' \
"echo 'Error: Either env var \$PVPN_PASSWORD or \$PVPN_PASSWORD_FILE is required.'" \
"exit 1" \
"fi" \
"" \
'[ -f "$PVPN_USERNAME_FILE" ] && PVPN_USERNAME=$(cat "$PVPN_USERNAME_FILE")' \
'[ -f "$PVPN_PASSWORD_FILE" ] && PVPN_PASSWORD=$(cat "$PVPN_PASSWORD_FILE")' \
"pvpn-cli || exit" \
'ip link show proton0 > /dev/null 2>&1 || exit' \
'fallback="$(expr ${NATPMP_TIMEOUT} \* 3 / 4)"' \
@ -94,7 +93,7 @@ RUN printf "%s\n" \
" while true" \
" do" \
' echo "Refreshing NAT-PMP port forwarding…"' \
' natpmpc -a 0 0 udp "$NATPMP_TIMEOUT"' \
' natpmp -a 0 0 udp "$NATPMP_TIMEOUT"' \
' natpmpc -a 0 0 tcp "$NATPMP_TIMEOUT"' \
' echo "NAT-PMP port forwarding has been refreshed!"' \
' sleep "$NATPMP_INTERVAL"' \
@ -102,7 +101,7 @@ RUN printf "%s\n" \
"} &" \
"set -m" \
'[ ${MAX_UPTIME:-0} -gt 0 ] && {' \
' sudo -iu '"${USERNAME}"' rtorrent -o network.port_range.set=$port-$port,system.daemon.set=true $@ &' \
' soudo -iu '"${USERNAME}"' rtorrent -o network.port_range.set=$port-$port,system.daemon.set=true $@ &' \
' pid=$!' \
' sleep "$MAX_UPTIME"' \
' pkill -9 $pid' \

View file

@ -10,6 +10,7 @@ begin
set -l services \
$server \
$turn turn "" \
$office $officeDomain
source "$dir/../service.fish"
@ -93,40 +94,10 @@ begin
end
end
function getServiceLocations -V services -V office -a index
function getServiceLocations -V services -a index
set -l i (math (math (math $index - 1) / 2 "*" 3) + 1)
set -l name $services[$i]
if [ "$name" != "$office" ]
printf "%s\0" "$name" / ""
else
printf "%s\0" \
"$name" "^~ /browser" "static files" \
"$name" "^~ /hosting/discovery" "WOPI discovery URL" \
"$name" "^~ /hosting/capabilities" "Capabilities" \
"$name" "~ ^/cool/(.*)/ws\$" "main websocket" \
"$name" "~ ^/(c|l)ool" "download, presentation and image upload" \
"$name" "^~ /cool/adminws" "Admin Console websocket"
end
end
function getServiceLocationConfig -a domain s location -V office -V flood
if [ "$s" = "$office" ]
set -l argv $argv[4..]
getServiceDefaultProxy $domain $s "$location" --scheme https $argv
else
getServiceDefaultProxy $argv --path "$location"
end
end
function getExtraLocationSettings -a domain s location -V service
if string match --regex '^(~ \^|\^~ )/cool/(.*)ws\$?$' "$location" >/dev/null
printf "%s\n" \
'# Websocket' \
"proxy_http_version 1.1;" \
'proxy_set_header Upgrade $http_upgrade;' \
'proxy_set_header Connection "upgrade";'
end
printf "%s\0" "$name" /
end
function getExtraBackupPatterns

View file

@ -8,4 +8,4 @@ services:
image: postgres
restart: unless-stopped
volumes:
- ./data/db:/var/lib/postgresql/data
- ./database:/var/lib/postgresql/data

View file

@ -68,31 +68,24 @@ begin
echo "$domain"
end
function getExtraServerConfig -a domain
function getExtraServerConfig -a subdomain domain
end
function getServiceLocationConfig -a domain service location
getServiceDefaultProxy $domain $service $location $argv
getServiceDefaultProxy $domain $service $location "" $argv
end
function getServiceDefaultProxy -a domain service location
argparse -i "comment=" "path=" "scheme=" "url=" -- $argv
set -l scheme
argparse -i "comment=" "path=" "url=" -- $argv
set -l url
set -l config (getServiceOverrides $argv)
set -l portKey (getServicePortKey "$service")
set -l port (yq "$portKey" "$config" | extractPort)
if [ -n "$_flag_scheme" ]
set scheme "$_flag_scheme"
else
set scheme http
end
if [ -n "$_flag_url" ]
set url "$_flag_url"
else
set url "$scheme://127.0.0.1:$port"
set url "http://127.0.0.1:$port"
if [ -n "$_flag_path" ]
set url "$url$_flag_path"
@ -100,10 +93,10 @@ begin
end
printf "%s\n" \
"location $location {" \
(if [ -n "$_flag_comment" ]
echo "# $_flag_comment"
end) \
"location $location {" \
"proxy_pass $url;" \
'proxy_set_header Host $host;' \
'proxy_set_header X-Real-IP $remote_addr;' \
@ -134,7 +127,7 @@ begin
for i in (seq 1 2 (count $servers))
set -l locations (getServiceLocations $i $argv | string split0)
for j in (seq 1 3 (count $locations))
for j in (seq 1 2 (count $locations))
set -l file (mktemp)
set -l port (getRandomPort)
set -l service $locations[$j]
@ -165,17 +158,11 @@ begin
"server {" \
"listen 80;" \
"server_name $domain;" \
(getExtraServerConfig $domain $argv)
(getExtraServerConfig $subdomain $domain $argv)
for j in (seq 1 3 (count $locations))
for j in (seq 1 2 (count $locations))
set -l service $locations[$j]
set -l location $locations[(math $j + 1)]
set -l comment $locations[(math $j + 2)]
if [ -n "$comment" ]
set -a argv --comment "$comment"
end
getServiceLocationConfig $domain $service $location $argv
end

View file

@ -4,7 +4,5 @@ services:
restart: unless-stopped
tty: true
stdin_open: true
ports:
- 7777:7777
volumes:
- ./data:/root/.local/share/Terraria/Worlds

View file

@ -4,6 +4,7 @@ services:
restart: unless-stopped
depends_on:
- db
user: 1337:1337
environment:
WRITABLE_PATH: /data
MONGO_URL: mongodb://db:27017/wekan

View file

@ -18,28 +18,12 @@ begin
installDockerService $argv
end
function configureSW -V dir
configureDockerService $argv
end
function getServiceServers -V domain
printf "%s\0" $domain
end
function getServiceLocations -V service
printf "%s\0" \
"$service" / "static files" \
"$service" "~ ^/sockjs/.*/websocket\$" "Websocket"
end
function getExtraLocationSettings -a domain s location -V service
if [ "$location" != "/" ]
printf "%s\n" \
'# Websocket' \
"proxy_http_version 1.1;" \
'proxy_set_header Upgrade $http_upgrade;' \
'proxy_set_header Connection "upgrade";'
end
printf "%s\0" "$service" /
end
runInstaller --force $argv

View file

@ -23,10 +23,9 @@ end
function restoreFiles
if [ -n "$VALHALLA_BACKUP_DIR" ]
set -l path (getArchivePath $argv)
argparse -i "user=" "base-directory=" -- $argv
set -l tarArgs
set -l sudoArgs
argparse -i "user=" "base-directory=" -- $argv
if [ -n "$_flag_base_directory" ]
set -a tarArgs -C "$_flag_base_directory"
@ -38,8 +37,8 @@ function restoreFiles
set -a sudoArgs -u "$_flag_user"
end
if runRestorationCommand test -f "$path"
runRestorationCommand cat "$path" | sudo $sudoArgs tar $tarArgs -xvz
fetchArchive $argv | begin
sudo $sudoArgs tar $tarArgs -xvz
end
end
end
@ -48,22 +47,22 @@ function createArchive -a path
runRestorationCommand sh -c "tee $(string escape -- "$path") >/dev/null"
end
function fetchArchive
set -l path (getArchivePath $argv)
runRestorationCommand cat "$path"
end
function runRestorationCommand
if [ -z "$VALHALLA_BACKUP_SERVER" ]
$argv
else
set -l args
set -l host "$VALHALLA_BACKUP_SERVER"
if [ -n "$VALHALLA_BACKUP_SERVER_USER" ]
set host "$VALHALLA_BACKUP_SERVER_USER@$host"
end
if [ -n "$VALHALLA_BACKUP_SERVER_PORT" ]
set -a args -p $VALHALLA_BACKUP_SERVER_PORT
end
sudo ssh -i $(string escape -- "$VALHALLA_BACKUP_SERVER_KEY") $args "$host" (string escape -- $argv)
sudo ssh -i $(string escape -- "$VALHALLA_BACKUP_SERVER_KEY") $args "$VALHALLA_BACKUP_SERVER" (string escape -- $argv)
end
end
@ -71,7 +70,7 @@ function getArchivePath
argparse -i "u/user=" "n/name=" -- $argv
set -l path "$VALHALLA_BACKUP_DIR"
if [ -n "$_flag_user" ]
if [ -b "$_flag_user" ]
set -a path Users "$_flag_user"
else
set -a path System

View file

@ -18,7 +18,7 @@ begin
"lxc.mount.entry = $(realpath "$dir/../..") $valhallaRoot none bind 0 0" \
"" \
"# VPN" \
"lxc.cgroup2.devices.allow = c 10:200 rwm" \
"lxc.cgroup.devices.allow = c 10:200 rwm" \
"lxc.mount.entry = /dev/net dev/net none bind,create=dir 0 0"
end | sudo tee -a "$containerDir/config" >/dev/null