diff --git a/ct/opengym.sh b/ct/opengym.sh deleted file mode 100644 index 61ace72e19..0000000000 --- a/ct/opengym.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bash -_CS_DEFAULT_URL="https://raw.githubusercontent.com/community-scripts/DevScripts/main" -_cs_boot="${COMMUNITY_SCRIPTS_CORE_DIR:-$(dirname "${BASH_SOURCE[0]}")/../../core}/core/build.func" -source "$_cs_boot" 2>/dev/null || source <(curl -fsSL "${COMMUNITY_SCRIPTS_CORE_URL:-https://raw.githubusercontent.com/community-scripts/core/main}/core/build.func") -# Copyright (c) 2021-2026 community-scripts ORG -# Author: MickLesk (CanbiZ) -# License: MIT | https://github.com/community-scripts/DevScripts/raw/main/LICENSE -# Source: https://github.com/DuarteSantos8/openGym - -APP="openGym" -var_tags="${var_tags:-health;fitness}" -var_cpu="${var_cpu:-2}" -var_ram="${var_ram:-2048}" -var_disk="${var_disk:-4}" -var_os="${var_os:-debian}" -var_version="${var_version:-13}" -var_arm64="${var_arm64:-yes}" -var_unprivileged="${var_unprivileged:-1}" - -header_info "$APP" -variables -color -catch_errors - -function update_script() { - header_info - check_container_storage - check_container_resources - - if [[ ! -d /opt/opengym ]]; then - msg_error "No openGym Installation Found!" - exit - fi - - if check_for_gh_release "opengym" "DuarteSantos8/openGym" "" "" "v"; then - msg_info "Stopping openGym" - systemctl stop nginx opengym - msg_ok "Stopped openGym" - - NODE_VERSION="22" setup_nodejs - CLEAN_INSTALL=1 fetch_and_deploy_gh_release "opengym" "DuarteSantos8/openGym" "tarball" "latest" "/opt/opengym" "" "v" - - msg_info "Building openGym" - cd /opt/opengym/api - $STD npm ci --omit=dev --omit=optional - cd /opt/opengym/frontend - $STD npm ci --ignore-scripts - $STD npm run build - rm -rf /opt/opengym/frontend/node_modules ~/.npm - msg_ok "Built openGym" - - msg_info "Starting openGym" - systemctl start opengym nginx - msg_ok "Started openGym" - msg_ok "Updated successfully!" - fi - exit -} - -start -build_container -description - -msg_ok "Completed Successfully!\n" -echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" -echo -e "${INFO}${YW}Access it using the following URL:${CL}" -echo -e "${GATEWAY}${BGN}http://${IP}${CL}" -echo -e "${INFO}${YW}Sign-in is by password over plain HTTP. Create your profile right away: the first one becomes the admin.${CL}" -echo -e "${INFO}${YW}For passkeys, serve it over HTTPS on a hostname through a reverse proxy, then set RP_ID and ORIGIN in /opt/opengym_data/.env and run systemctl restart opengym. Changing RP_ID later invalidates existing passkeys.${CL}" diff --git a/install/opengym-install.sh b/install/opengym-install.sh deleted file mode 100644 index 05d339a352..0000000000 --- a/install/opengym-install.sh +++ /dev/null @@ -1,158 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) 2021-2026 community-scripts ORG -# Author: MickLesk (CanbiZ) -# License: MIT | https://github.com/community-scripts/DevScripts/raw/main/LICENSE -# Source: https://github.com/DuarteSantos8/openGym - -source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" -color -verb_ip6 -catch_errors -setting_up_container -network_check -update_os - -msg_info "Installing Dependencies" -$STD apt install -y nginx -msg_ok "Installed Dependencies" - -NODE_VERSION="22" setup_nodejs -fetch_and_deploy_gh_release "opengym" "DuarteSantos8/openGym" "tarball" "latest" "/opt/opengym" "" "v" - -msg_info "Building openGym" -cd /opt/opengym/api -$STD npm ci --omit=dev --omit=optional -cd /opt/opengym/frontend -# Like upstream's web/Dockerfile: skips sharp's libvips download, which only draws the mobile app icons -$STD npm ci --ignore-scripts -$STD npm run build -rm -rf /opt/opengym/frontend/node_modules ~/.npm -msg_ok "Built openGym" - -msg_info "Configuring openGym" -mkdir -p /opt/opengym_data -cat </opt/opengym_data/.env -PORT=3000 -DATA_DIR=/opt/opengym_data -RP_NAME=openGym -# Passkeys need HTTPS on a hostname. Behind a reverse proxy set both to the address in the browser, -# e.g. RP_ID=gym.example.com and ORIGIN=https://gym.example.com, then: systemctl restart opengym -RP_ID=${LOCAL_IP} -ORIGIN=http://${LOCAL_IP} -PASSWORD_LOGIN=1 -FIRST_USER_ADMIN=1 -EOF -chmod 600 /opt/opengym_data/.env -msg_ok "Configured openGym" - -msg_info "Creating openGym Service" -cat </etc/systemd/system/opengym.service -[Unit] -Description=openGym API -After=network.target - -[Service] -Type=simple -User=root -WorkingDirectory=/opt/opengym/api -EnvironmentFile=/opt/opengym_data/.env -Environment=NODE_ENV=production -ExecStart=/usr/bin/node server.js -Restart=on-failure -RestartSec=5 - -[Install] -WantedBy=multi-user.target -EOF -systemctl enable -q --now opengym -msg_ok "Created openGym Service" - -msg_info "Configuring Nginx" -cat <<'EOF' >/etc/nginx/sites-available/opengym -server { - listen 80 default_server; - server_name _; - root /opt/opengym/frontend/dist; - index index.html; - absolute_redirect off; - - add_header X-Frame-Options "DENY" always; - add_header X-Content-Type-Options "nosniff" always; - add_header Referrer-Policy "same-origin" always; - add_header Content-Security-Policy "frame-ancestors 'none'" always; - - location ^~ /api/ { - client_max_body_size 5m; - proxy_pass http://127.0.0.1:3000; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header CF-Connecting-IP ""; - proxy_read_timeout 300s; - proxy_send_timeout 300s; - } - - location ^~ /api/media/ { - client_max_body_size 48m; - proxy_request_buffering off; - proxy_buffering off; - proxy_pass http://127.0.0.1:3000; - proxy_http_version 1.1; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header CF-Connecting-IP ""; - proxy_read_timeout 300s; - proxy_send_timeout 300s; - } - - location / { - try_files $uri $uri/ @root; - } - - location @root { - return 302 /$is_args$args; - } - - location ~* \.(js|css|json|html)$ { - add_header Cache-Control "no-cache, must-revalidate"; - add_header X-Frame-Options "DENY" always; - add_header X-Content-Type-Options "nosniff" always; - add_header Referrer-Policy "same-origin" always; - add_header Content-Security-Policy "frame-ancestors 'none'" always; - } - - location ^~ /exercise-media/ { - alias /opt/opengym/catalogue/media/; - add_header Cache-Control "public, max-age=2592000, immutable"; - add_header Cross-Origin-Resource-Policy "same-origin" always; - add_header X-Frame-Options "DENY" always; - add_header X-Content-Type-Options "nosniff" always; - add_header Referrer-Policy "same-origin" always; - add_header Content-Security-Policy "frame-ancestors 'none'" always; - } - - location ~* \.(png|jpg|jpeg|gif|ico|svg|woff|woff2|webp|avif|mp4)$ { - add_header Cache-Control "public, max-age=2592000, immutable"; - add_header X-Frame-Options "DENY" always; - add_header X-Content-Type-Options "nosniff" always; - add_header Referrer-Policy "same-origin" always; - add_header Content-Security-Policy "frame-ancestors 'none'" always; - } - - gzip on; - gzip_types text/plain text/css application/json application/javascript image/svg+xml; - gzip_vary on; - gzip_min_length 1024; -} -EOF -nginx_enable_site "opengym" -msg_ok "Configured Nginx" - -motd_ssh -customize -cleanup_lxc diff --git a/json/opengym.json b/json/opengym.json deleted file mode 100644 index 0e68f3877f..0000000000 --- a/json/opengym.json +++ /dev/null @@ -1,77 +0,0 @@ -{ - "name": "openGym", - "slug": "opengym", - "categories": [ - 24 - ], - "date_created": "2026-10-11", - "type": "ct", - "updateable": true, - "privileged": false, - "interface_port": 80, - "documentation": "https://github.com/DuarteSantos8/openGym/blob/main/docs/SELF_HOSTING.md", - "website": "https://opengym.ch/", - "repository": "https://github.com/DuarteSantos8/openGym", - "architectures": [ - "amd64", - "arm64" - ], - "logo": "https://cdn.jsdelivr.net/gh/DuarteSantos8/openGym@main/frontend/public/icon-512.png", - "description": "openGym is a self-hosted gym and body-weight tracker. Plan weekly routines, log workouts with supersets and cardio, track body weight, measurements and personal records, and browse a library of more than 5,600 exercises with animations. Every profile keeps its own data and syncs across devices; the web app installs to the home screen, and an Android app can pair with your server. This script builds the web app from source and runs the Node.js API behind nginx.", - "install_methods": [ - { - "type": "default", - "script": "ct/opengym.sh", - "config_path": "/opt/opengym_data/.env", - "resources": { - "cpu": 2, - "ram": 2048, - "hdd": 4, - "os": "Debian", - "version": "13" - } - } - ], - "default_credentials": { - "username": null, - "password": null - }, - "notes": [ - { - "text": "openGym is served over plain HTTP at http:// with password sign-in switched on (PASSWORD_LOGIN=1): choose Create new profile and pick a name and a password. Passkeys, the app's default, cannot work on an IP address, because browsers only offer them on HTTPS under a hostname, so the sign-in screen offers passwords until you switch as described below.", - "type": "info" - }, - { - "text": "The first profile created becomes the admin (FIRST_USER_ADMIN=1), so create yours right after the install. Anyone who can reach the address can create a profile; to close signup, set INVITE_ONLY=1 (and ALLOW_GUEST=0 to remove guest mode) in /opt/opengym_data/.env after your own profile exists, then run systemctl restart opengym.", - "type": "warning" - }, - { - "text": "Over plain HTTP the password and the session cookie cross the network unencrypted. Keep openGym on a network you trust, or put it behind HTTPS as described below.", - "type": "warning" - }, - { - "text": "ORIGIN in /opt/opengym_data/.env must be exactly the address in the browser bar (http:// as installed). If the container's IP changes or you open openGym under a hostname, set ORIGIN and RP_ID to that address and run systemctl restart opengym; until then sign-ins fail with \"cross-origin request refused\".", - "type": "info" - }, - { - "text": "Passkeys: put openGym behind a reverse proxy or tunnel that terminates HTTPS for a real hostname (Caddy, Nginx Proxy Manager, Traefik, Cloudflare Tunnel) and points at http://:80, set RP_ID=gym.example.com and ORIGIN=https://gym.example.com in /opt/opengym_data/.env, then run systemctl restart opengym. Profiles made with a password keep signing in and can add a passkey under Settings > Account > Passkeys. Settle on the hostname before people register passkeys: changing RP_ID later invalidates every passkey made under the old one.", - "type": "info" - }, - { - "text": "There is deliberately no self-signed certificate on the IP: an IP address can never be a passkey hostname, and browsers refuse service workers on untrusted certificates, so it would add a certificate warning and enable nothing. Push notifications, Keep screen awake and offline use also need a trusted HTTPS address.", - "type": "info" - }, - { - "text": "The Android app pairs with the plain http:// address: sign in on the website, then use Settings > Account > Pair the mobile app.", - "type": "info" - }, - { - "text": "Accounts, workouts, uploaded photos and videos and the key that signs every session live in /opt/opengym_data together with the .env; back up that folder. Updates replace /opt/opengym and leave it untouched.", - "type": "info" - }, - { - "text": "Install and every update build the web app from source with Node.js 22, which peaks at about 0.9 GB of RAM. The running app needs about 150 MB.", - "type": "info" - } - ] -}