Schaut gut aus, will aber nicht
Seit Beginn meiner kleinen Seite wollte ich eine Kommentarfunktion haben. Aber nachdem ich nicht einfach Disqus und Konsorten einbinden wollte und mir ständig andere Sachen dazwischen kommen, habe ich es immer wieder aufgeschoben. Bis jetzt, denn letztens bin ich auf das Open Source Projekt Talkyard gestoßen.
Ich dachte mir es wird schon nicht so schwer sein, das auf einen LXC-Container zu installieren. Und ja, das geht sogar, die Software läuft. Das Problem war dann, dass Talkyard Nginx verwendet und ich aber Caddy für Zertifikate und als Reverse Proxy verwende. Daher wollte ich Nginx nur für die statischen Websiten-Elemente verwenden und stattdessen Caddy für den Rest. Aber das war leider nicht erfolgreich. Dieser Beitrag ist dennoch vielleicht für jemanden insteressant, wer weiß.
Installation
Hier das Github-Repo. Als Erstes erstellen wir einen Klon von unserem Docker-LXC, falls man kein Template hat, kann man auch einen neuen LXC-Container mit beispielsweise Ubuntu 24.04 oder Debian 12 erstellen (oder auch Alpine Linux, wenn man es kompakt haben möchte). Dann passt man die IP-Adresse an, am besten mit statischer Adresse oder fixer Vergabe vom DHCP-Server.
Jetzt können wir den Container starten und die folgenden Befehle ausführen (vgl. Anleitung auf Github):
apt update
apt upgrade
apt install git locales
apt install tree ncdu
locale-gen en_US.UTF-8
export LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
Die Programme tree
und ncdu
werden nur dazu benutzt um eine schöne Baumansicht im Terminal zu bekommen (tree
) und die Ordnergröße im gegeben Verzeichnis anzeigen zu lassen (ncdu
). Die locales
Installation ist unter Ubuntu 24.04 nicht notwendig, bei anderen Distros kann sie aber fehlen. Ich habe aus der Liste eigentlich nur den Editor vim
ausgelassen, denn der sollte entweder eh schon installiert sein und wenn nicht, hat man auf die Schnelle auch gar nichts damit angefangen – auch wenn es durchaus erstrebenswert wäre endlich umzusteigen, bin ich nach wie vor bei nano
.
Den nächsten Schritt kann man überspringen, wenn man ein entsprechendes Monitoring hat, oder nicht davon ausgeht die Platte vollzuschreiben (unter Proxmox alles nicht so ein großes Problem, da man jederzeit die virtual hard disk erweitern kann):
Es wirkt mir überhaupt wie ein etwas komischer Mechanismus, einfach ein paar “Platzhalter” Dateien zu erstellen, die dann wie bei einem Heißluftballon, wie die Gewichte, abgeworfen werden. Denn wenn Talkyard alles vollräumt, dann steht die Bude sowieso erst einmal und ob ich dann diese “Speicherplatz-Gewichtln” lösche oder [[0L Raspberry Pi SD-Karte voll So mistet man das System aus|zum Beispiel den apt
-Cache]] ist dann auch schon wurst.
Als nächstes müssen wir das Github-Repo klonen. Sie empfehlen /opt/talkyard
weil sonst “das Backup nicht funktioniert”. Naja, von mir aus:
cd /opt/
git clone https://github.com/debiki/talkyard-prod-one.git talkyard
cd talkyard
Interessant, dass die Installationsanleitung für eine produktive Umgebung im Grunde aus einem Haufen Skripte besteht, so wie hier im nächsten Schritt (für LXC habe ich ein angepasstes prepare-os.sh
-Skript erstellt1):
./scripts/prepare-os.sh 2>&1 | tee -a talkyard-maint.log
Auch wenn mehrmals in Klammern darauf hingewiesen wird, die Skripte doch etwas zu beäugen:
Aber das hat nicht neugierig gemacht, was heißt hier “enable automatic security updates”? Naja, schauen wir uns einmal an, was das Skript so macht. Aber vorher erstelle ich noch einen Snapshot, damit wir schnell und einfach wieder zum Zustand davor zurückkehren können:
2025-04-07T15:13:37+00:00 prepare-os: Configuring this Operating System:
Generating locales (this might take a while)...
en_US.UTF-8... done
Generation complete.
Setting LC_ALL to en_US.UTF-8...
2025-04-07T15:13:40+00:00 prepare-os: Installing jq and rng-tools, for json logs and hardware random numbers...
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Note, selecting 'rng-tools-debian' instead of 'rng-tools'
The following additional packages will be installed:
libjq1 libonig5
The following NEW packages will be installed:
jq libjq1 libonig5 rng-tools-debian
0 upgraded, 4 newly installed, 0 to remove and 0 not upgraded.
Need to get 421 kB of archives.
After this operation, 1,251 kB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu noble/universe amd64 rng-tools-debian amd64 2.4 [42.7 kB]
Get:2 http://archive.ubuntu.com/ubuntu noble/main amd64 libonig5 amd64 6.9.9-1build1 [172 kB]
Get:3 http://archive.ubuntu.com/ubuntu noble/main amd64 libjq1 amd64 1.7.1-3build1 [141 kB]
Get:4 http://archive.ubuntu.com/ubuntu noble/main amd64 jq amd64 1.7.1-3build1 [65.5 kB]
Fetched 421 kB in 1s (503 kB/s)
Selecting previously unselected package rng-tools-debian.
(Reading database ... 20796 files and directories currently installed.)
Preparing to unpack .../rng-tools-debian_2.4_amd64.deb ...
Unpacking rng-tools-debian (2.4) ...
Selecting previously unselected package libonig5:amd64.
Preparing to unpack .../libonig5_6.9.9-1build1_amd64.deb ...
Unpacking libonig5:amd64 (6.9.9-1build1) ...
Selecting previously unselected package libjq1:amd64.
Preparing to unpack .../libjq1_1.7.1-3build1_amd64.deb ...
Unpacking libjq1:amd64 (1.7.1-3build1) ...
Selecting previously unselected package jq.
Preparing to unpack .../jq_1.7.1-3build1_amd64.deb ...
Unpacking jq (1.7.1-3build1) ...
Setting up rng-tools-debian (2.4) ...
Setting up libonig5:amd64 (6.9.9-1build1) ...
Setting up libjq1:amd64 (1.7.1-3build1) ...
Setting up jq (1.7.1-3build1) ...
Processing triggers for man-db (2.12.0-4build2) ...
Processing triggers for libc-bin (2.39-0ubuntu8.4) ...
2025-04-07T15:13:47+00:00 prepare-os: Installing add-apt-repository...
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
appstream dirmngr gir1.2-packagekitglib-1.0 gpg gpg-agent gpgconf libappstream5 libduktape207 libdw1t64 libglib2.0-bin libgstreamer1.0-0 libksba8
libpackagekit-glib2-18 libpolkit-agent-1-0 libpolkit-gobject-1-0 libstemmer0d libxmlb2 packagekit packagekit-tools pinentry-curses polkitd python3-blinker
python3-cryptography python3-distro python3-httplib2 python3-jwt python3-launchpadlib python3-lazr.restfulclient python3-lazr.uri python3-oauthlib
python3-pyparsing python3-six python3-software-properties python3-wadllib sgml-base unattended-upgrades xml-core
Suggested packages:
apt-config-icons gnupg pinentry-gnome3 tor keyboxd scdaemon gstreamer1.0-tools pinentry-doc polkitd-pkla python-blinker-doc python-cryptography-doc
python3-cryptography-vectors python3-crypto python3-keyring python3-testresources python-pyparsing-doc sgml-base-doc bsd-mailx needrestart powermgmt-base
debhelper
The following NEW packages will be installed:
appstream dirmngr gir1.2-packagekitglib-1.0 gpg gpg-agent gpgconf libappstream5 libduktape207 libdw1t64 libglib2.0-bin libgstreamer1.0-0 libksba8
libpackagekit-glib2-18 libpolkit-agent-1-0 libpolkit-gobject-1-0 libstemmer0d libxmlb2 packagekit packagekit-tools pinentry-curses polkitd python3-blinker
python3-cryptography python3-distro python3-httplib2 python3-jwt python3-launchpadlib python3-lazr.restfulclient python3-lazr.uri python3-oauthlib
python3-pyparsing python3-six python3-software-properties python3-wadllib sgml-base software-properties-common unattended-upgrades xml-core
0 upgraded, 38 newly installed, 0 to remove and 0 not upgraded.
Need to get 5,787 kB of archives.
After this operation, 21.7 MB of additional disk space will be used.
Get:1 http://archive.ubuntu.com/ubuntu noble/main amd64 sgml-base all 1.31 [11.4 kB]
{...}
Creating config file /etc/apt/apt.conf.d/20auto-upgrades with new version
Creating config file /etc/apt/apt.conf.d/50unattended-upgrades with new version
Created symlink /etc/systemd/system/multi-user.target.wants/unattended-upgrades.service → /usr/lib/systemd/system/unattended-upgrades.service.
Synchronizing state of unattended-upgrades.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable unattended-upgrades
Setting up python3-pyparsing (3.1.1-1) ...
Setting up python3-cryptography (41.0.7-4ubuntu0.1) ...
Setting up python3-wadllib (1.3.6-5) ...
Setting up libduktape207:amd64 (2.7.0+tests-0ubuntu3) ...
Setting up gpgconf (2.4.4-2ubuntu17.2) ...
Setting up python3-httplib2 (0.20.4-3) ...
Setting up sgml-base (1.31) ...
Setting up libstemmer0d:amd64 (2.2.0-4build1) ...
Setting up gpg (2.4.4-2ubuntu17.2) ...
Setting up libpolkit-gobject-1-0:amd64 (124-2ubuntu1.24.04.2) ...
Setting up libgstreamer1.0-0:amd64 (1.24.2-1ubuntu0.1) ...
Setcap worked! gst-ptp-helper is not suid!
Setting up python3-blinker (1.7.0-1) ...
Setting up gpg-agent (2.4.4-2ubuntu17.2) ...
Created symlink /etc/systemd/user/sockets.target.wants/gpg-agent.socket → /usr/lib/systemd/user/gpg-agent.socket.
Created symlink /etc/systemd/user/sockets.target.wants/gpg-agent-ssh.socket → /usr/lib/systemd/user/gpg-agent-ssh.socket.
Created symlink /etc/systemd/user/sockets.target.wants/gpg-agent-extra.socket → /usr/lib/systemd/user/gpg-agent-extra.socket.
Created symlink /etc/systemd/user/sockets.target.wants/gpg-agent-browser.socket → /usr/lib/systemd/user/gpg-agent-browser.socket.
Setting up libappstream5:amd64 (1.0.2-1build6) ...
Setting up dirmngr (2.4.4-2ubuntu17.2) ...
Created symlink /etc/systemd/user/sockets.target.wants/dirmngr.socket → /usr/lib/systemd/user/dirmngr.socket.
Setting up python3-oauthlib (3.2.2-1) ...
Setting up appstream (1.0.2-1build6) ...
✔ Metadata cache was updated successfully.
Setting up xml-core (0.19) ...
Setting up libpolkit-agent-1-0:amd64 (124-2ubuntu1.24.04.2) ...
Setting up python3-lazr.restfulclient (0.14.6-1) ...
Setting up python3-launchpadlib (1.11.0-6) ...
Created symlink /etc/systemd/user/timers.target.wants/launchpadlib-cache-clean.timer → /usr/lib/systemd/user/launchpadlib-cache-clean.timer.
Setting up python3-software-properties (0.99.49.1) ...
Processing triggers for libc-bin (2.39-0ubuntu8.4) ...
Processing triggers for man-db (2.12.0-4build2) ...
Processing triggers for dbus (1.14.10-4ubuntu4.1) ...
Processing triggers for sgml-base (1.31) ...
Setting up polkitd (124-2ubuntu1.24.04.2) ...
Creating group 'polkitd' with GID 989.
Creating user 'polkitd' (User for polkitd) with UID 989 and GID 989.
Setting up packagekit (1.2.8-2ubuntu1.2) ...
Created symlink /etc/systemd/user/sockets.target.wants/pk-debconf-helper.socket → /usr/lib/systemd/user/pk-debconf-helper.socket.
Setting up packagekit-tools (1.2.8-2ubuntu1.2) ...
Setting up software-properties-common (0.99.49.1) ...
Processing triggers for dbus (1.14.10-4ubuntu4.1) ...
2025-04-07T15:14:04+00:00 prepare-os: Amending the /etc/sysctl.conf config...
2025-04-07T15:14:04+00:00 prepare-os: Reloading the system config...
* Applying /usr/lib/sysctl.d/10-apparmor.conf ...
* Applying /etc/sysctl.d/10-bufferbloat.conf ...
* Applying /etc/sysctl.d/10-console-messages.conf ...
* Applying /etc/sysctl.d/10-ipv6-privacy.conf ...
* Applying /etc/sysctl.d/10-kernel-hardening.conf ...
* Applying /etc/sysctl.d/10-magic-sysrq.conf ...
* Applying /etc/sysctl.d/10-map-count.conf ...
* Applying /etc/sysctl.d/10-network-security.conf ...
* Applying /etc/sysctl.d/10-ptrace.conf ...
* Applying /etc/sysctl.d/10-zeropage.conf ...
* Applying /usr/lib/sysctl.d/50-pid-max.conf ...
* Applying /usr/lib/sysctl.d/99-protect-links.conf ...
* Applying /etc/sysctl.d/99-sysctl.conf ...
* Applying /etc/sysctl.conf ...
sysctl: setting key "kernel.apparmor_restrict_unprivileged_userns", ignoring: Read-only file system
kernel.apparmor_restrict_unprivileged_userns = 1
sysctl: setting key "kernel.printk", ignoring: Read-only file system
kernel.printk = 4 4 1 7
net.ipv6.conf.all.use_tempaddr = 2
net.ipv6.conf.default.use_tempaddr = 2
sysctl: setting key "kernel.kptr_restrict", ignoring: Read-only file system
kernel.kptr_restrict = 1
sysctl: setting key "kernel.sysrq", ignoring: Read-only file system
kernel.sysrq = 176
sysctl: setting key "vm.max_map_count", ignoring: Read-only file system
vm.max_map_count = 1048576
net.ipv4.conf.default.rp_filter = 2
net.ipv4.conf.all.rp_filter = 2
sysctl: setting key "kernel.yama.ptrace_scope", ignoring: Read-only file system
kernel.yama.ptrace_scope = 1
sysctl: setting key "vm.mmap_min_addr", ignoring: Read-only file system
vm.mmap_min_addr = 65536
sysctl: setting key "kernel.pid_max", ignoring: Read-only file system
kernel.pid_max = 4194304
sysctl: setting key "fs.protected_fifos", ignoring: Read-only file system
fs.protected_fifos = 1
sysctl: setting key "fs.protected_hardlinks", ignoring: Read-only file system
fs.protected_hardlinks = 1
sysctl: setting key "fs.protected_regular", ignoring: Read-only file system
fs.protected_regular = 2
sysctl: setting key "fs.protected_symlinks", ignoring: Read-only file system
fs.protected_symlinks = 1
sysctl: setting key "vm.swappiness", ignoring: Read-only file system
vm.swappiness = 0
net.core.somaxconn = 8192
sysctl: setting key "vm.max_map_count", ignoring: Read-only file system
vm.max_map_count = 262144
sysctl: setting key "vm.swappiness", ignoring: Read-only file system
vm.swappiness = 0
net.core.somaxconn = 8192
sysctl: setting key "vm.max_map_count", ignoring: Read-only file system
vm.max_map_count = 262144
Transparent Huge Pages is [madvise] or [never], fine, Redis happy.
2025-04-07T15:14:04+00:00 prepare-os: Adding history settings to .bashrc...
2025-04-07T15:14:04+00:00 prepare-os: There's already an auto upgrades config file: /etc/apt/apt.conf.d/20auto-upgrades.
2025-04-07T15:14:04+00:00 prepare-os: I'll leave it as is — I won't (re)configure automatic upgrades.
2025-04-07T15:14:04+00:00 prepare-os: ---- It's contents: ------
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
2025-04-07T15:14:04+00:00 prepare-os: --------------------------
2025-04-07T15:14:04+00:00 prepare-os: Consider adding the below line, if it's missing,
2025-04-07T15:14:04+00:00 prepare-os: so your server will reboot if needed, for upgrades to take effect:
Unattended-Upgrade::Automatic-Reboot "true";
2025-04-07T15:14:04+00:00 prepare-os: Done configuring the OS.
OK, alle Befehle, die eine komplette VM benötigen funktionieren in einem unprivilegierten Container nicht. Darunter Sicherheitseinstellungen:
sysctl: setting key "kernel.apparmor_restrict_unprivileged_userns", ignoring: Read-only file system
Und u.A. Swapeinstellungen:
sysctl: setting key "vm.swappiness", ignoring: Read-only file system
vm.swappiness = 0
Aber Swap habe ich sowieso nicht, sollte aber auch ohne ausreichen. Die Kernel-Apparmor Einstellungen muss ich eventuell noch über die Container Config einrichten.
Der chinesische Chatbot schlägt folgende Anpassungen für LXC mit dem Skript vor:
Machen wir einmal weiter, bis wir wo anstehen.
Die nächsten beiden Schritte können wir gleich überspringen, denn Docker Compose ist hier bereits installiert und Proxmox hat bereits eine Firewall, die wir verwenden werden.
Jetzt müssen wir die .env
im Repo-Ordner und play-framework.conf
im Unterordner conf
anpassen:
Mit dem Befehl…
openssl rand -base64 32
… bekommt man ein 32-Zeichen langes zufällig generiertes Passwort für POSTGRES_PASSWORD=change_me
in .env
.
Für conf/play-framework.conf
braucht man noch einmal ein Passwort, dieses Mal achtzig Zeichen lang (openssl rand -base64 80
) und man muss auch Administrator-Email, URL und Angaben für den Emailversand vom Forum mittels SMTP eintragen.
Als nächstes wieder in das Hauptverzeichnis von der Repo wechseln und je nach RAM-Ausstattung den passenden Befehl ausführen. Hier für 1,7 GB freien RAM:
cp mem/1.7g.yml docker-compose.override.yml
Jetzt noch einmal einen Snapshot anlegen und dann…
./scripts/upgrade-if-needed.sh 2>&1 | tee -a talkyard-maint.log
… ausführen. Was leider misslingt:
root@talkyard:/opt/talkyard# ./scripts/upgrade-if-needed.sh 2>&1 | tee -a talkyard-maint.log
upgrade-script: Using release branch: tyse-v0-regular.
upgrade-script: Apparently no version currently installed.
upgrade-script: Checking for latest version...
upgrade-script: Downloading version numbers submodule...
Submodule 'versions' (https://github.com/debiki/talkyard-versions.git) registered for path 'versions'
Cloning into '/opt/talkyard/versions'...
Submodule path 'versions': checked out 'ebf65a424af5f9fa6ac22bae5cd07958cd264f5f'
Previous HEAD position was ebf65a4 Add v0.5.0-WIP-4-6f60d0c.
Switched to a new branch 'tyse-v0-regular'
branch 'tyse-v0-regular' set up to track 'origin/tyse-v0-regular'.
upgrade-script: I will install version v0.2025.005-7a6728209.
upgrade-script: Downloading version v0.2025.005-7a6728209... (this might take long)
./scripts/upgrade-if-needed.sh: line 126: /usr/local/bin/docker-compose: No such file or directory
Das liegt wohl daran, dass die Anleitung noch die alte Variante mit docker-compose
verwendet und nicht die als Plugin realisierte neue Variante als docker compose
. Das Verzeichnis docker-compose
existiert nicht, da alles in docker
ist. Wo genau mit which docker
findet man zB folgenden Pfad:
/usr/bin/docker
Um dieses Problem zu lösen muss man, laut Chatbot, zuerst den falschen Verweis…
… durch den richtigen ersetzen:
Um das Skript anzupassen kann man diesen Befehl verwenden:
sed -i 's|/usr/local/bin/docker-compose|docker compose|g' scripts/upgrade-if-needed.sh
Jetzt lädt es herunter:
root@talkyard:/opt/talkyard# ./scripts/upgrade-if-needed.sh 2>&1 | tee -a talkyard-maint.log
upgrade-script: Using release branch: tyse-v0-regular.
upgrade-script: Apparently no version currently installed.
upgrade-script: Checking for latest version...
Reset branch 'tyse-v0-regular'
branch 'tyse-v0-regular' set up to track 'origin/tyse-v0-regular'.
Your branch is up to date with 'origin/tyse-v0-regular'.
upgrade-script: I will install version v0.2025.005-7a6728209.
upgrade-script: Downloading version v0.2025.005-7a6728209... (this might take long)
msg="/opt/talkyard/docker-compose.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion"
msg="/opt/talkyard/docker-compose.override.yml: the attribute `version` is obsolete, it will be ignored, please remove it to avoid potential confusion"
cache Pulling
rdb Pulling
search Pulling
app Pulling
web Pulling
Aber das Starten funktioniert nicht:
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error setting rlimits for ready process: error setting rlimit type 8: operation not permitted: unknown
Deepseek meint es liegt an
So in etwa:
Und das Docker-Deployment hat funktioniert:
upgrade-script: Installing: Setting current version number to v0.2025.005-7a6728209...
upgrade-script: Done. Bye.
Talkyard aufrufen → mehr Troubleshooting
Aber so wirklich funktioniert hat das nicht, als ich die Website via IP-Adresse aufrufen wollte (sowohl mit http als auch https):
Die talkyard-app
scheint auch so ihre Probleme zu haben:
Die Anleitung ist auch nicht unbedingt hilfreich…
… und der nächste Schritt hat wieder drei Skripte, die aber nur für die maintenance wichtig sind:
Ich habe also nun das docker-compose.yml
angepasst
Caddyfile:
forum.martinfellner.at {
reverse_proxy http://xxx.xxx.xxx.xxx:80 {
# Tell Talkyard the original request was HTTPS:
header_up X-Forwarded-Proto https
header_up X-Forwarded-Host {host}
header_up X-Real-IP {remote}
}
}
Aber wenn man nur diese Einstellung nimmt, dann bekommt man den folgenden Fehler, beim Aufrufen der Seite:
403 Forbidden
X-Forwarded-Proto is Some(http) but should be https. X-Forwarded-Host: Some(forum.martinfellner.at) [TyEFORWPROTO]
Daher muss man dann doch noch conf/sites-enabled-manual/talkyard-servers.conf
anpassen, oder durch diese Version ersetzen (Server URL bei server_name
eingeben nicht vergessen):
server {
listen 80;
server_name forum.website.com;
# Serve static assets directly
location /-/assets/ {
alias /opt/talkyard/uploads/;
expires 1y;
add_header Cache-Control "public";
access_log off;
}
location /-/fonts/ {
alias /opt/talkyard/uploads/fonts/;
expires 1y;
add_header Cache-Control "public";
access_log off;
}
location /-/media/ {
alias /opt/talkyard/uploads/media/;
expires 1y;
add_header Cache-Control "public";
access_log off;
}
# Proxy dynamic requests to Play Framework
location / {
proxy_pass http://app:9000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Das sind die Chatbot’schen Änderungen:
Jetzt muss man noch Nginx neustarten mit:
docker compose restart web
Und es funktioniert nicht. Ich schaffe es auch nach mehreren Versuchen nicht Talkyard aufzurufen. Ich glaube das wird’s nicht mehr.
Letztlich ist der Versuch gescheitert und ich bin dann auf NodeBB umgestiegen. Aber vielleicht ist es ja interessant zu sehen, dass man Talkyard prinzipiell auch in einem kleinen LXC Container installieren kann.
#!/bin/bash
# This script makes ElasticSearch work, simplifies troubleshooting,
# and configures automatic security updates, with reboots.
# ADAPTED FOR PROXMOX LXC + DOCKER
function log_message {
echo "`date --iso-8601=seconds --utc` prepare-os: $1"
}
echo
echo
log_message 'Configuring this Operating System (Proxmox LXC):'
# ----------------------------------------------------------------------
# 1. Locale Settings
# ----------------------------------------------------------------------
# Avoid "warning: Setting locale failed" warnings from Perl
locale-gen 'en_US.UTF-8'
if ! grep -q 'LC_ALL=' /etc/default/locale; then
echo 'Setting LC_ALL to en_US.UTF-8...'
echo 'LC_ALL=en_US.UTF-8' >> /etc/default/locale
export LC_ALL='en_US.UTF-8'
fi
if ! grep -q 'LANG=' /etc/default/locale; then
echo 'Setting LANG to en_US.UTF-8...'
echo 'LANG=en_US.UTF-8' >> /etc/default/locale
export LANG='en_US.UTF-8'
fi
# ----------------------------------------------------------------------
# 2. Install Dependencies
# ----------------------------------------------------------------------
# Install 'jq' for JSON logs (skip rng-tools in LXC)
log_message 'Installing jq...'
apt-get -y install jq
log_message 'Installing add-apt-repository...'
apt-get -y install software-properties-common
# ----------------------------------------------------------------------
# 3. Sysctl Settings (LXC-Compatible Only)
# ----------------------------------------------------------------------
# Omit vm.max_map_count (must be set on Proxmox host instead)
if ! grep -q 'Talkyard' /etc/sysctl.conf; then
log_message 'Amending /etc/sysctl.conf for LXC...'
cat <<-EOF >> /etc/sysctl.conf
###################################################################
# Talkyard LXC settings
vm.swappiness=0
net.core.somaxconn=8192
EOF
log_message 'Reloading sysctl (LXC-safe settings)...'
sysctl --system
fi
# ----------------------------------------------------------------------
# 4. Transparent Huge Pages (THP) for Redis (Conditional)
# ----------------------------------------------------------------------
if [ -f /sys/kernel/mm/transparent_hugepage/enabled ]; then
if ! grep -q '\[always\]' /sys/kernel/mm/transparent_hugepage/enabled ; then
echo "Transparent Huge Pages: [madvise] or [never], Redis-compatible."
else
echo "Setting Transparent Huge Pages to [madvise] for Redis..."
echo madvise > /sys/kernel/mm/transparent_hugepage/enabled
rc_local_f="/etc/rc.local"
if [ ! -f $rc_local_f ]; then
echo "exit 0" >> $rc_local_f
fi
if ! grep -q 'transparent_hugepage/enabled' $rc_local_f ; then
sed -i -e '$i # For Talkyard and Redis:\necho madvise > /sys/kernel/mm/transparent_hugepage/enabled\n' $rc_local_f
fi
fi
else
log_message "Skipping THP adjustment: /sys/kernel/mm/transparent_hugepage/enabled not accessible in LXC."
fi
# ----------------------------------------------------------------------
# 5. Bash History (Troubleshooting)
# ----------------------------------------------------------------------
if ! grep -q 'HISTTIMEFORMAT' ~/.bashrc; then
log_message 'Adding history settings to .bashrc...'
cat <<-EOF >> ~/.bashrc
###################################################################
export HISTCONTROL=ignoredups
export HISTCONTROL=ignoreboth
export HISTSIZE=10100
export HISTFILESIZE=10100
export HISTTIMEFORMAT='%F %T %z '
EOF
fi
# ----------------------------------------------------------------------
# 6. Automatic Security Updates (With Safeguards)
# ----------------------------------------------------------------------
auto_upgr_f="/etc/apt/apt.conf.d/20auto-upgrades"
if [ -f $auto_upgr_f ]; then
log_message "Auto-upgrades config already exists. Leaving it intact."
else
log_message 'Enabling automatic security updates (no reboots by default)...'
DEBIAN_FRONTEND=noninteractive \
apt-get install -y \
-o Dpkg::Options::="--force-confdef" \
-o Dpkg::Options::="--force-confold" \
unattended-upgrades \
update-notifier-common
cat <<EOF > $auto_upgr_f
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
APT::Periodic::AutoremoveInterval "14";
APT::Periodic::AutocleanInterval "14";
APT::Periodic::MinAge "8";
Unattended-Upgrade::Automatic-Reboot "false"; # Safer for Docker in LXC
EOF
fi
# ----------------------------------------------------------------------
log_message 'Done configuring the OS for Proxmox LXC + Docker.'
echo
Footnotes
-
Hier das für unprivilegierte Proxmox LXC angepasste Skript: ↩