Skip to content

Commit d667482

Browse files
Merge pull request #1389 from FlorisCl/feature/expand-wger-install-script
Expand wger script with celery and gunnicorn
2 parents e31f8ee + f76e30f commit d667482

3 files changed

Lines changed: 171 additions & 68 deletions

File tree

ct/wger.sh

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function update_script() {
3131

3232
if check_for_gh_release "wger" "wger-project/wger"; then
3333
msg_info "Stopping Service"
34-
systemctl stop apache2
34+
systemctl stop redis-server nginx celery celery-beat wger
3535
msg_ok "Stopped Service"
3636

3737
msg_info "Backing up Data"
@@ -45,6 +45,7 @@ function update_script() {
4545
cp -r /opt/wger_media_backup/. /opt/wger/media
4646
cp /opt/wger_env_backup /opt/wger/.env
4747
rm -rf /opt/wger_media_backup /opt/wger_env_backup
48+
4849
msg_ok "Restored Data"
4950

5051
msg_info "Updating wger"
@@ -56,9 +57,9 @@ function update_script() {
5657
$STD uv run python manage.py collectstatic --no-input
5758
msg_ok "Updated wger"
5859

59-
msg_info "Starting Service"
60-
systemctl start apache2
61-
msg_ok "Started Service"
60+
msg_info "Starting Services"
61+
systemctl start redis-server nginx celery celery-beat wger
62+
msg_ok "Started Services"
6263
msg_ok "Updated Successfully"
6364
fi
6465
exit
@@ -71,4 +72,4 @@ description
7172
msg_ok "Completed Successfully!\n"
7273
echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}"
7374
echo -e "${INFO}${YW} Access it using the following URL:${CL}"
74-
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
75+
echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:3000${CL}"

frontend/public/json/wger.json

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"name": "wger",
3+
"slug": "wger",
4+
"categories": [
5+
24
6+
],
7+
"date_created": "2025-02-24",
8+
"type": "ct",
9+
"updateable": true,
10+
"privileged": false,
11+
"interface_port": 3000,
12+
"documentation": "https://wger.readthedocs.io/en/latest/index.html",
13+
"website": "https://wger.de",
14+
"logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/wger.webp",
15+
"config_path": "/opt/wger/wger.env",
16+
"description": "wger (ˈvɛɡɐ) Workout Manager is a free, open source web application that helps you manage your personal workouts, weight and diet plans and can also be used as a simple gym management utility. It offers a REST API as well, for easy integration with other projects and tools.",
17+
"install_methods": [
18+
{
19+
"type": "default",
20+
"script": "ct/wger.sh",
21+
"resources": {
22+
"cpu": 2,
23+
"ram": 2048,
24+
"hdd": 8,
25+
"os": "debian",
26+
"version": "13"
27+
}
28+
}
29+
],
30+
"default_credentials": {
31+
"username": "admin",
32+
"password": "adminadmin"
33+
},
34+
"notes": [
35+
{
36+
"text": "This LXC also runs Celery and Redis to synchronize workouts and ingredients",
37+
"type": "info"
38+
}
39+
]
40+
}

install/wger-install.sh

Lines changed: 125 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,18 @@ network_check
1414
update_os
1515

1616
msg_info "Installing Dependencies"
17-
$STD apt-get install -y \
18-
apache2 \
19-
libapache2-mod-wsgi-py3 \
17+
$STD apt install -y \
18+
build-essential \
19+
nginx \
20+
redis-server \
2021
libpq-dev
2122
msg_ok "Installed Dependencies"
2223

24+
import_local_ip
2325
NODE_VERSION="22" NODE_MODULE="sass" setup_nodejs
2426
setup_uv
25-
2627
PG_VERSION="16" setup_postgresql
2728
PG_DB_NAME="wger" PG_DB_USER="wger" setup_postgresql_db
28-
2929
fetch_and_deploy_gh_release "wger" "wger-project/wger" "tarball" "latest" "/opt/wger"
3030

3131
msg_info "Setting up wger"
@@ -36,85 +36,147 @@ $STD corepack enable
3636
$STD npm install
3737
$STD npm run build:css:sass
3838
$STD uv venv
39-
$STD uv pip install .
39+
$STD uv pip install . --group docker
4040
SECRET_KEY=$(openssl rand -base64 40)
4141
cat <<EOF >/opt/wger/.env
42+
DJANGO_SETTINGS_MODULE=settings.main
43+
PYTHONPATH=/opt/wger
44+
4245
DJANGO_DB_ENGINE=django.db.backends.postgresql
4346
DJANGO_DB_DATABASE=${PG_DB_NAME}
4447
DJANGO_DB_USER=${PG_DB_USER}
4548
DJANGO_DB_PASSWORD=${PG_DB_PASS}
4649
DJANGO_DB_HOST=localhost
4750
DJANGO_DB_PORT=5432
51+
DATABASE_URL=postgresql://${PG_DB_USER}:${PG_DB_PASS}@localhost:5432/${PG_DB_NAME}
52+
4853
DJANGO_MEDIA_ROOT=/opt/wger/media
4954
DJANGO_STATIC_ROOT=/opt/wger/static
50-
SECRET_KEY=${SECRET_KEY}
51-
EOF
52-
cat <<'WSGI' >/opt/wger/wsgi_wrapper.py
53-
import os
54-
from pathlib import Path
55+
DJANGO_STATIC_URL=/static/
56+
57+
ALLOWED_HOSTS=${LOCAL_IP},localhost,127.0.0.1
58+
CSRF_TRUSTED_ORIGINS=http://${LOCAL_IP}:3000
5559
56-
env_file = Path('/opt/wger/.env')
57-
if env_file.exists():
58-
for line in env_file.read_text().splitlines():
59-
if line.strip() and not line.startswith('#') and '=' in line:
60-
key, value = line.split('=', 1)
61-
os.environ.setdefault(key.strip(), value.strip())
60+
USE_X_FORWARDED_HOST=True
61+
SECURE_PROXY_SSL_HEADER=HTTP_X_FORWARDED_PROTO,http
6262
63-
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'settings.main')
63+
DJANGO_CACHE_BACKEND=django_redis.cache.RedisCache
64+
DJANGO_CACHE_LOCATION=redis://127.0.0.1:6379/1
65+
DJANGO_CACHE_TIMEOUT=300
66+
DJANGO_CACHE_CLIENT_CLASS=django_redis.client.DefaultClient
67+
AXES_CACHE_ALIAS=default
6468
65-
from wger.wsgi import application
66-
WSGI
69+
USE_CELERY=True
70+
CELERY_BROKER=redis://127.0.0.1:6379/2
71+
CELERY_BACKEND=redis://127.0.0.1:6379/2
72+
73+
SITE_URL=http://${LOCAL_IP}:3000
74+
SECRET_KEY=${SECRET_KEY}
75+
EOF
6776
set -a && source /opt/wger/.env && set +a
68-
export DJANGO_SETTINGS_MODULE=settings.main
69-
$STD uv run python manage.py migrate
70-
$STD uv run python manage.py loaddata languages
71-
$STD uv run python manage.py loaddata gym_config
72-
$STD uv run python manage.py loaddata groups
73-
$STD uv run python manage.py loaddata site
77+
$STD uv run wger bootstrap
7478
$STD uv run python manage.py collectstatic --no-input
7579
cat <<EOF | uv run python manage.py shell
7680
from django.contrib.auth import get_user_model
77-
UserModel = get_user_model()
78-
user = UserModel.objects.create_user('admin', email='admin@localhost', password='${PG_DB_PASS}')
79-
user.is_superuser = True
80-
user.is_staff = True
81-
user.save()
81+
User = get_user_model()
82+
83+
user, created = User.objects.get_or_create(
84+
username="admin",
85+
defaults={"email": "admin@localhost"},
86+
)
87+
88+
if created:
89+
user.set_password("${PG_DB_PASS}")
90+
user.is_superuser = True
91+
user.is_staff = True
92+
user.save()
8293
EOF
8394
msg_ok "Set up wger"
95+
msg_info "Creating Config and Services"
96+
cat <<EOF >/etc/systemd/system/wger.service
97+
[Unit]
98+
Description=wger Gunicorn
99+
After=network.target
100+
101+
[Service]
102+
User=root
103+
WorkingDirectory=/opt/wger
104+
EnvironmentFile=/opt/wger/.env
105+
ExecStart=/opt/wger/.venv/bin/gunicorn \
106+
--bind 127.0.0.1:8000 \
107+
--workers 3 \
108+
--threads 2 \
109+
--timeout 120 \
110+
wger.wsgi:application
111+
Restart=always
112+
113+
[Install]
114+
WantedBy=multi-user.target
115+
EOF
116+
cat <<EOF >/etc/systemd/system/celery.service
117+
[Unit]
118+
Description=wger Celery Worker
119+
After=network.target redis-server.service
120+
Requires=redis-server.service
121+
122+
[Service]
123+
WorkingDirectory=/opt/wger
124+
EnvironmentFile=/opt/wger/.env
125+
ExecStart=/opt/wger/.venv/bin/celery -A wger worker -l info
126+
Restart=always
127+
128+
[Install]
129+
WantedBy=multi-user.target
130+
EOF
84131

85-
msg_info "Creating Service"
86-
cat <<EOF >/etc/apache2/sites-available/wger.conf
87-
<Directory /opt/wger>
88-
<Files wsgi_wrapper.py>
89-
Require all granted
90-
</Files>
91-
</Directory>
92-
93-
<VirtualHost *:80>
94-
WSGIApplicationGroup %{GLOBAL}
95-
WSGIDaemonProcess wger python-path=/opt/wger python-home=/opt/wger/.venv
96-
WSGIProcessGroup wger
97-
WSGIScriptAlias / /opt/wger/wsgi_wrapper.py
98-
WSGIPassAuthorization On
99-
100-
Alias /static/ /opt/wger/static/
101-
<Directory /opt/wger/static>
102-
Require all granted
103-
</Directory>
104-
105-
Alias /media/ /opt/wger/media/
106-
<Directory /opt/wger/media>
107-
Require all granted
108-
</Directory>
109-
110-
ErrorLog /var/log/apache2/wger-error.log
111-
CustomLog /var/log/apache2/wger-access.log combined
112-
</VirtualHost>
132+
mkdir -p /var/lib/wger/celery
133+
chmod 700 /var/lib/wger/celery
134+
cat <<EOF >/etc/systemd/system/celery-beat.service
135+
[Unit]
136+
Description=wger Celery Beat
137+
After=network.target redis-server.service
138+
Requires=redis-server.service
139+
140+
[Service]
141+
WorkingDirectory=/opt/wger
142+
EnvironmentFile=/opt/wger/.env
143+
ExecStart=/opt/wger/.venv/bin/celery -A wger beat -l info \
144+
--schedule /var/lib/wger/celery/celerybeat-schedule
145+
Restart=always
146+
147+
[Install]
148+
WantedBy=multi-user.target
149+
EOF
150+
cat <<'EOF' >/etc/nginx/sites-available/wger
151+
server {
152+
listen 3000;
153+
server_name _;
154+
155+
client_max_body_size 20M;
156+
157+
location /static/ {
158+
alias /opt/wger/static/;
159+
expires 30d;
160+
}
161+
162+
location /media/ {
163+
alias /opt/wger/media/;
164+
}
165+
166+
location / {
167+
proxy_pass http://127.0.0.1:8000;
168+
proxy_set_header Host $host;
169+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
170+
proxy_set_header X-Forwarded-Proto $scheme;
171+
proxy_redirect off;
172+
}
173+
}
113174
EOF
114-
$STD a2dissite 000-default.conf
115-
$STD a2ensite wger
116-
systemctl restart apache2
117-
msg_ok "Created Service"
175+
$STD rm -f /etc/nginx/sites-enabled/default
176+
$STD ln -sf /etc/nginx/sites-available/wger /etc/nginx/sites-enabled/wger
177+
systemctl enable -q --now redis-server nginx wger celery celery-beat
178+
systemctl restart nginx
179+
msg_ok "Created Config and Services"
118180

119181
motd_ssh
120182
customize

0 commit comments

Comments
 (0)