feature: root service and account status
This commit is contained in:
@ -16,6 +16,7 @@ By: Codex (GPT-5)
|
|||||||
| 28.12.2025 | 🏗️ Planning | ID: PR-Vorbereitung fuer feature/oidc-validation geplant. By: Codex (GPT-5) |
|
| 28.12.2025 | 🏗️ Planning | ID: PR-Vorbereitung fuer feature/oidc-validation geplant. By: Codex (GPT-5) |
|
||||||
| 28.12.2025 | 🏗️ Planning | ID: PAM immer aktiv; OIDC optional mit deaktivierter UI-Option dokumentiert. By: Codex (GPT-5) |
|
| 28.12.2025 | 🏗️ Planning | ID: PAM immer aktiv; OIDC optional mit deaktivierter UI-Option dokumentiert. By: Codex (GPT-5) |
|
||||||
| 28.12.2025 | ⚙️ Code | ID: Installer setzt PAM-Defaults in /etc/skd/env. By: Codex (GPT-5) |
|
| 28.12.2025 | ⚙️ Code | ID: Installer setzt PAM-Defaults in /etc/skd/env. By: Codex (GPT-5) |
|
||||||
|
| 28.12.2025 | ⚙️ Code | ID: Root-Service auf Port 80, Account-Status und Self-Disable-Schutz. By: Codex (GPT-5) |
|
||||||
|
|
||||||
---
|
---
|
||||||
## Legende
|
## Legende
|
||||||
|
|||||||
2
Makefile
2
Makefile
@ -8,7 +8,7 @@ ENV_FILE ?= $(ENV_DIR)/env
|
|||||||
SYSTEMD_PATH ?= /etc/systemd/system/$(SERVICE).service
|
SYSTEMD_PATH ?= /etc/systemd/system/$(SERVICE).service
|
||||||
BRANCH ?= main
|
BRANCH ?= main
|
||||||
HOST ?= 127.0.0.1
|
HOST ?= 127.0.0.1
|
||||||
PORT ?= 8000
|
PORT ?= 80
|
||||||
HEALTH_URL ?= http://$(HOST):$(PORT)/health
|
HEALTH_URL ?= http://$(HOST):$(PORT)/health
|
||||||
TOKEN ?= $(shell awk -F= '/^SKD_AUTH_TOKEN=/{print $$2}' $(ENV_FILE) 2>/dev/null)
|
TOKEN ?= $(shell awk -F= '/^SKD_AUTH_TOKEN=/{print $$2}' $(ENV_FILE) 2>/dev/null)
|
||||||
KEEP_INSTALL_DIR ?= 1
|
KEEP_INSTALL_DIR ?= 1
|
||||||
|
|||||||
22
README.md
22
README.md
@ -16,7 +16,7 @@ cd /opt/sk
|
|||||||
./scripts/install.sh
|
./scripts/install.sh
|
||||||
sudo systemctl status skd.service
|
sudo systemctl status skd.service
|
||||||
```
|
```
|
||||||
Then open `http://localhost:8000/` and log in via PAM (default) to start quickly.
|
Then open `http://localhost/` and log in via PAM (default) to start quickly.
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
Set in `/etc/skd/env` (see `env.example`):
|
Set in `/etc/skd/env` (see `env.example`):
|
||||||
@ -36,12 +36,12 @@ Notes:
|
|||||||
- `./scripts/install.sh` will create `/etc/skd/env` from `env.example` if missing (edit afterwards) and ensure the `skd` service user/group exist.
|
- `./scripts/install.sh` will create `/etc/skd/env` from `env.example` if missing (edit afterwards) and ensure the `skd` service user/group exist.
|
||||||
|
|
||||||
## OIDC Setup
|
## OIDC Setup
|
||||||
OIDC ist optional. Wenn der Provider noch nicht bereit ist, bleibe bei `SKD_AUTH_MODE=pam`.
|
OIDC ist optional. PAM bleibt immer verfuegbar; `SKD_AUTH_MODE` ist optional.
|
||||||
1. Issuer muss der externen URL des Providers entsprechen (TLS trust erforderlich).
|
1. Issuer muss der externen URL des Providers entsprechen (TLS trust erforderlich).
|
||||||
2. OIDC Client registrieren (DCR), z.B.:
|
2. OIDC Client registrieren (DCR), z.B.:
|
||||||
```bash
|
```bash
|
||||||
export SKD_OIDC_ISSUER="https://auth.example.org"
|
export SKD_OIDC_ISSUER="https://auth.example.org"
|
||||||
export SKD_OIDC_REDIRECT_URI="https://<device-host>[:port]/login/oidc/callback"
|
export SKD_OIDC_REDIRECT_URI="https://<device-host>/login/oidc/callback"
|
||||||
export OIDC_INITIAL_ACCESS_TOKEN="<initial-access-token>"
|
export OIDC_INITIAL_ACCESS_TOKEN="<initial-access-token>"
|
||||||
./scripts/register_oidc_client.sh
|
./scripts/register_oidc_client.sh
|
||||||
```
|
```
|
||||||
@ -61,11 +61,11 @@ Hinweise:
|
|||||||
- Allowlist fuer OIDC: `SKD_AUTH_ALLOWED_USERS` prueft `preferred_username`, `email` oder `sub`.
|
- Allowlist fuer OIDC: `SKD_AUTH_ALLOWED_USERS` prueft `preferred_username`, `email` oder `sub`.
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
- Service: managed by systemd; `./scripts/install.sh` writes the unit dynamically to `/etc/systemd/system/skd.service` with the current repo path and restarts it.
|
- Service: managed by systemd; `./scripts/install.sh` writes the unit dynamically to `/etc/systemd/system/skd.service` with the current repo path and restarts it (runs as root for PAM).
|
||||||
- Manual run: `./scripts/run.sh` (uses `.venv`, defaults to `0.0.0.0:8000`).
|
- Manual run: `./scripts/run.sh` (uses `.venv`, defaults to `0.0.0.0:80`).
|
||||||
- Login (PAM): `curl -X POST -H "Content-Type: application/json" -d '{"username":"root","password":"..."}' http://localhost:8000/login`
|
- Login (PAM): `curl -X POST -H "Content-Type: application/json" -d '{"username":"root","password":"..."}' http://localhost/login`
|
||||||
- Login (OIDC): open `http://localhost:8000/login/oidc/start` → provider → redirected back with session cookie set.
|
- Login (OIDC): open `http://localhost/login/oidc/start` → provider → redirected back with session cookie set.
|
||||||
- Health: `curl -H "Authorization: Bearer <token>" http://localhost:8000/health`
|
- Health: `curl -H "Authorization: Bearer <token>" http://localhost/health`
|
||||||
|
|
||||||
## OIDC Validation & Fallbacks
|
## OIDC Validation & Fallbacks
|
||||||
- Validierungsschritte: `docs/oidc-validation.md` (State, Token-Exchange, Claims, Cookie).
|
- Validierungsschritte: `docs/oidc-validation.md` (State, Token-Exchange, Claims, Cookie).
|
||||||
@ -74,7 +74,7 @@ Hinweise:
|
|||||||
- Bei Self-Signed TLS: CA im System trusten oder in Dev PAM nutzen.
|
- Bei Self-Signed TLS: CA im System trusten oder in Dev PAM nutzen.
|
||||||
|
|
||||||
## API (Bearer token via `/login`)
|
## API (Bearer token via `/login`)
|
||||||
- `GET /users` → `[{user, logged_in}]` (manageable system users; excludes root)
|
- `GET /users` → `[{user, logged_in, account_locked}]` (manageable system users; excludes root)
|
||||||
- `POST /users/{name}/disable` with JSON `{countdown?, sound?, message?}`
|
- `POST /users/{name}/disable` with JSON `{countdown?, sound?, message?}`
|
||||||
- `POST /users/{name}/enable`
|
- `POST /users/{name}/enable`
|
||||||
- `GET /health`
|
- `GET /health`
|
||||||
@ -82,11 +82,11 @@ Hinweise:
|
|||||||
|
|
||||||
Example:
|
Example:
|
||||||
```bash
|
```bash
|
||||||
token=$(curl -s -X POST -H "Content-Type: application/json" -d '{"username":"root","password":"..."}' http://localhost:8000/login | jq -r .token)
|
token=$(curl -s -X POST -H "Content-Type: application/json" -d '{"username":"root","password":"..."}' http://localhost/login | jq -r .token)
|
||||||
curl -X POST -H "Authorization: Bearer $token" \
|
curl -X POST -H "Authorization: Bearer $token" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
-d '{"countdown":90,"sound":true}' \
|
-d '{"countdown":90,"sound":true}' \
|
||||||
http://localhost:8000/users/child1/disable
|
http://localhost/users/child1/disable
|
||||||
```
|
```
|
||||||
|
|
||||||
## Web UI
|
## Web UI
|
||||||
|
|||||||
@ -138,7 +138,6 @@ def disable_user(
|
|||||||
steps.append("sessions terminated")
|
steps.append("sessions terminated")
|
||||||
except subprocess.CalledProcessError as exc:
|
except subprocess.CalledProcessError as exc:
|
||||||
if exc.returncode == 1:
|
if exc.returncode == 1:
|
||||||
# pkill returns 1 when no matching processes exist; not an error here.
|
|
||||||
steps.append("no sessions to terminate")
|
steps.append("no sessions to terminate")
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|||||||
@ -159,15 +159,15 @@ def users(settings: Settings = Depends(get_settings)) -> List[UserStatus]:
|
|||||||
dependencies=[Depends(get_current_admin)],
|
dependencies=[Depends(get_current_admin)],
|
||||||
)
|
)
|
||||||
def disable_user(
|
def disable_user(
|
||||||
current_user: str = Depends(get_current_admin),
|
|
||||||
username: str = Depends(validate_user),
|
username: str = Depends(validate_user),
|
||||||
payload: ActionRequest | None = Body(default=None),
|
payload: ActionRequest | None = Body(default=None),
|
||||||
settings: Settings = Depends(get_settings),
|
settings: Settings = Depends(get_settings),
|
||||||
|
current_user: str = Depends(get_current_admin),
|
||||||
) -> ActionResponse:
|
) -> ActionResponse:
|
||||||
if username == current_user:
|
if username == current_user:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=status.HTTP_400_BAD_REQUEST,
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
detail="Refusing to disable the currently authenticated user",
|
detail="Cannot disable current user",
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
steps = actions.disable_user(
|
steps = actions.disable_user(
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import datetime as dt
|
|||||||
import grp
|
import grp
|
||||||
import pwd
|
import pwd
|
||||||
import spwd
|
import spwd
|
||||||
from typing import List, Set, Optional
|
from typing import List, Optional, Set
|
||||||
|
|
||||||
import jwt
|
import jwt
|
||||||
import pam
|
import pam
|
||||||
@ -123,14 +123,9 @@ def list_manageable_users(settings: Settings) -> List[str]:
|
|||||||
|
|
||||||
|
|
||||||
def is_account_locked(username: str) -> bool:
|
def is_account_locked(username: str) -> bool:
|
||||||
"""Return True when the account is locked in /etc/shadow."""
|
|
||||||
try:
|
try:
|
||||||
shadow_entry = spwd.getspnam(username)
|
entry = spwd.getspnam(username)
|
||||||
except KeyError:
|
except (KeyError, PermissionError):
|
||||||
return False
|
return False
|
||||||
except PermissionError:
|
password_hash = entry.sp_pwdp or ""
|
||||||
return False
|
return password_hash.startswith(("!", "*"))
|
||||||
shadow_password = shadow_entry.sp_pwdp or ""
|
|
||||||
if shadow_password in ("*", "!", "!!"):
|
|
||||||
return True
|
|
||||||
return shadow_password.startswith("!")
|
|
||||||
|
|||||||
@ -154,9 +154,7 @@
|
|||||||
statusDiv.textContent = 'Lade...';
|
statusDiv.textContent = 'Lade...';
|
||||||
try {
|
try {
|
||||||
const data = await api('/users');
|
const data = await api('/users');
|
||||||
statusDiv.textContent = data
|
statusDiv.textContent = data.map(u => `${u.user}: ${u.account_locked ? 'deaktiviert' : 'aktiv'}, ${u.logged_in ? 'eingeloggt' : 'aus'}`).join('\n') || 'Keine Daten';
|
||||||
.map(u => `${u.user}: ${u.logged_in ? 'eingeloggt' : 'aus'} | ${u.account_locked ? 'deaktiviert' : 'aktiv'}`)
|
|
||||||
.join('\n') || 'Keine Daten';
|
|
||||||
const select = document.getElementById('username');
|
const select = document.getElementById('username');
|
||||||
select.innerHTML = '<option value="">-- wählen --</option>';
|
select.innerHTML = '<option value="">-- wählen --</option>';
|
||||||
data.forEach(u => {
|
data.forEach(u => {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ By: Codex (GPT-5)
|
|||||||
Validiere den OIDC-Login-Flow gegen einen realen oder Stub-Provider und dokumentiere Ergebnisse.
|
Validiere den OIDC-Login-Flow gegen einen realen oder Stub-Provider und dokumentiere Ergebnisse.
|
||||||
|
|
||||||
## Preconditions
|
## Preconditions
|
||||||
- Kiddo laeuft und ist erreichbar (z.B. `http://localhost:8000`).
|
- Kiddo laeuft und ist erreichbar (z.B. `http://localhost`).
|
||||||
- OIDC Provider oder Stub erreichbar.
|
- OIDC Provider oder Stub erreichbar.
|
||||||
- `SKD_AUTH_MODE=oidc` und `SKD_OIDC_*` gesetzt.
|
- `SKD_AUTH_MODE=oidc` und `SKD_OIDC_*` gesetzt.
|
||||||
- Redirect-URI: `https://<device-host>[:port]/login/oidc/callback` ist registriert.
|
- Redirect-URI: `https://<device-host>[:port]/login/oidc/callback` ist registriert.
|
||||||
@ -29,7 +29,7 @@ Validiere den OIDC-Login-Flow gegen einen realen oder Stub-Provider und dokument
|
|||||||
- Datum: 28.12.2025
|
- Datum: 28.12.2025
|
||||||
- Provider: nicht konfiguriert (IdP noch nicht bereit)
|
- Provider: nicht konfiguriert (IdP noch nicht bereit)
|
||||||
- Host/Redirect: n/a
|
- Host/Redirect: n/a
|
||||||
- Ergebnis: Blocked (Service nicht erreichbar unter http://localhost:8000/health)
|
- Ergebnis: Blocked (Service nicht erreichbar unter http://localhost/health)
|
||||||
- Fehlerbilder: curl (7) Couldn't connect to server
|
- Fehlerbilder: curl (7) Couldn't connect to server
|
||||||
|
|
||||||
## Fallbacks bei unvollstaendigem IdP
|
## Fallbacks bei unvollstaendigem IdP
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Copy to /etc/skd/env or .env for local runs
|
# Copy to /etc/skd/env or .env for local runs
|
||||||
# Optional allowlist of manageable users (otherwise all real users with uid>=1000)
|
# Optional allowlist of manageable users (otherwise all real users with uid>=1000)
|
||||||
SKD_ALLOWED_USERS=child1,child2
|
SKD_ALLOWED_USERS=
|
||||||
SKD_AUTH_SECRET=change-me-secret
|
SKD_AUTH_SECRET=change-me-secret
|
||||||
SKD_TOKEN_TTL_SECONDS=900
|
SKD_TOKEN_TTL_SECONDS=900
|
||||||
# PAM ist immer aktiv; OIDC wird zusaetzlich angeboten, wenn konfiguriert.
|
# PAM ist immer aktiv; OIDC wird zusaetzlich angeboten, wenn konfiguriert.
|
||||||
@ -13,7 +13,7 @@ SKD_AUTH_PAM_SERVICE=skd
|
|||||||
SKD_OIDC_ISSUER=
|
SKD_OIDC_ISSUER=
|
||||||
SKD_OIDC_CLIENT_ID=
|
SKD_OIDC_CLIENT_ID=
|
||||||
SKD_OIDC_CLIENT_SECRET=
|
SKD_OIDC_CLIENT_SECRET=
|
||||||
SKD_OIDC_REDIRECT_URI=http://localhost:8000/login/oidc/callback
|
SKD_OIDC_REDIRECT_URI=http://localhost/login/oidc/callback
|
||||||
SKD_OIDC_SCOPES=openid profile email
|
SKD_OIDC_SCOPES=openid profile email
|
||||||
SKD_SESSION_COOKIE_NAME=skd_session
|
SKD_SESSION_COOKIE_NAME=skd_session
|
||||||
SKD_SESSION_COOKIE_SECURE=false
|
SKD_SESSION_COOKIE_SECURE=false
|
||||||
|
|||||||
@ -10,7 +10,7 @@ Als Admin moechte ich verwaltbare Nutzer per API auflisten, damit ich ihren Logi
|
|||||||
## Akzeptanzkriterien
|
## Akzeptanzkriterien
|
||||||
- Given ein autorisierter Admin-Login
|
- Given ein autorisierter Admin-Login
|
||||||
- When ein GET auf `/users` erfolgt
|
- When ein GET auf `/users` erfolgt
|
||||||
- Then die Antwort ist eine Liste von Eintraegen mit `user` und `logged_in`
|
- Then die Antwort ist eine Liste von Eintraegen mit `user`, `logged_in` und `account_locked`
|
||||||
- And die Liste enthaelt nur verwaltbare, nicht-root Nutzer
|
- And die Liste enthaelt nur verwaltbare, nicht-root Nutzer
|
||||||
|
|
||||||
## Task-Platzhalter
|
## Task-Platzhalter
|
||||||
|
|||||||
@ -12,6 +12,7 @@ Als Admin moechte ich einen Nutzer per API deaktivieren, damit ich den Zugriff r
|
|||||||
- When ein POST auf `/users/{username}/disable` mit optionalen Feldern `countdown`, `sound`, `message` erfolgt
|
- When ein POST auf `/users/{username}/disable` mit optionalen Feldern `countdown`, `sound`, `message` erfolgt
|
||||||
- Then die Antwort enthaelt `user`, `action` = `disable`, `dry_run`, `steps` und `logged_in`
|
- Then die Antwort enthaelt `user`, `action` = `disable`, `dry_run`, `steps` und `logged_in`
|
||||||
- And nicht erlaubte Nutzer werden mit 403 abgewiesen
|
- And nicht erlaubte Nutzer werden mit 403 abgewiesen
|
||||||
|
- And der aktuell angemeldete Admin kann sich nicht selbst deaktivieren
|
||||||
|
|
||||||
## Task-Platzhalter
|
## Task-Platzhalter
|
||||||
- TASK_000005: API disable action (Details bei Story-Start)
|
- TASK_000005: API disable action (Details bei Story-Start)
|
||||||
|
|||||||
@ -11,6 +11,7 @@ Als Operator moechte ich den Service lokal starten, damit ich die API ohne Syste
|
|||||||
- Given eine vorhandene `.venv`
|
- Given eine vorhandene `.venv`
|
||||||
- When `scripts/run.sh` ausgefuehrt wird
|
- When `scripts/run.sh` ausgefuehrt wird
|
||||||
- Then `uvicorn` startet die App `backend.app:app` auf dem konfigurierten Host/Port
|
- Then `uvicorn` startet die App `backend.app:app` auf dem konfigurierten Host/Port
|
||||||
|
- And der Default-Port ist 80, wenn `PORT` nicht gesetzt ist
|
||||||
|
|
||||||
## Task-Platzhalter
|
## Task-Platzhalter
|
||||||
- TASK_000012: Run uvicorn service (Details bei Story-Start)
|
- TASK_000012: Run uvicorn service (Details bei Story-Start)
|
||||||
|
|||||||
@ -14,6 +14,7 @@ Als Operator moechte ich den Service installieren, damit er als Systemdienst lae
|
|||||||
- And das Projekt wird ins Install-Verzeichnis synchronisiert
|
- And das Projekt wird ins Install-Verzeichnis synchronisiert
|
||||||
- And eine Env-Datei wird aus `env.example` erstellt, falls sie fehlt
|
- And eine Env-Datei wird aus `env.example` erstellt, falls sie fehlt
|
||||||
- And eine Systemd-Unit wird geschrieben und der Service gestartet
|
- And eine Systemd-Unit wird geschrieben und der Service gestartet
|
||||||
|
- And die Unit startet als root und lauscht auf Port 80
|
||||||
|
|
||||||
## Task-Platzhalter
|
## Task-Platzhalter
|
||||||
- TASK_000013: Install service setup (Details bei Story-Start)
|
- TASK_000013: Install service setup (Details bei Story-Start)
|
||||||
|
|||||||
@ -11,6 +11,7 @@ Als Operator moechte ich eine Systemd-Unit im Repo haben, damit der Service stan
|
|||||||
- Given die Datei `systemd/skd.service` existiert
|
- Given die Datei `systemd/skd.service` existiert
|
||||||
- When die Unit inspiziert wird
|
- When die Unit inspiziert wird
|
||||||
- Then sie enthaelt Description, User/Group, WorkingDirectory, EnvironmentFile, ExecStart und Restart-Policy
|
- Then sie enthaelt Description, User/Group, WorkingDirectory, EnvironmentFile, ExecStart und Restart-Policy
|
||||||
|
- And der Dienst laeuft als root und lauscht auf Port 80
|
||||||
|
|
||||||
## Task-Platzhalter
|
## Task-Platzhalter
|
||||||
- TASK_000017: Systemd unit template (Details bei Story-Start)
|
- TASK_000017: Systemd unit template (Details bei Story-Start)
|
||||||
|
|||||||
@ -15,6 +15,7 @@ Als Admin moechte ich mich im Web-UI anmelden, Nutzer laden und Aktionen ausfueh
|
|||||||
- Then die Aktionsergebnisse (Steps/Status) werden als Text angezeigt
|
- Then die Aktionsergebnisse (Steps/Status) werden als Text angezeigt
|
||||||
- And Fehlerantworten werden als Text angezeigt
|
- And Fehlerantworten werden als Text angezeigt
|
||||||
- And die OIDC-Option ist deaktiviert, wenn keine Konfiguration vorliegt
|
- And die OIDC-Option ist deaktiviert, wenn keine Konfiguration vorliegt
|
||||||
|
- And der Status zeigt aktiv/deaktiviert pro Nutzer
|
||||||
|
|
||||||
## Task-Platzhalter
|
## Task-Platzhalter
|
||||||
- TASK_000022: UI login and actions (Details bei Story-Start)
|
- TASK_000022: UI login and actions (Details bei Story-Start)
|
||||||
|
|||||||
@ -5,7 +5,7 @@ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|||||||
SOURCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
SOURCE_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
||||||
|
|
||||||
SERVICE_NAME="${SERVICE_NAME:-skd}"
|
SERVICE_NAME="${SERVICE_NAME:-skd}"
|
||||||
SERVICE_USER="${SERVICE_USER:-skd}"
|
SERVICE_USER="${SERVICE_USER:-root}"
|
||||||
SERVICE_GROUP="${SERVICE_GROUP:-$SERVICE_USER}"
|
SERVICE_GROUP="${SERVICE_GROUP:-$SERVICE_USER}"
|
||||||
INSTALL_DIR="${INSTALL_DIR:-/opt/sk}"
|
INSTALL_DIR="${INSTALL_DIR:-/opt/sk}"
|
||||||
ENV_DIR="/etc/${SERVICE_NAME}"
|
ENV_DIR="/etc/${SERVICE_NAME}"
|
||||||
@ -109,11 +109,11 @@ After=network.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
User=${SERVICE_USER}
|
User=root
|
||||||
Group=${SERVICE_GROUP}
|
Group=root
|
||||||
WorkingDirectory=${INSTALL_DIR}
|
WorkingDirectory=${INSTALL_DIR}
|
||||||
EnvironmentFile=${ENV_FILE}
|
EnvironmentFile=${ENV_FILE}
|
||||||
ExecStart=${INSTALL_DIR}/.venv/bin/uvicorn backend.app:app --host 0.0.0.0 --port 8000
|
ExecStart=${INSTALL_DIR}/.venv/bin/uvicorn backend.app:app --host 0.0.0.0 --port 80
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=3
|
RestartSec=3
|
||||||
|
|
||||||
|
|||||||
@ -9,6 +9,6 @@ source .venv/bin/activate
|
|||||||
|
|
||||||
UVICORN_CMD=${UVICORN_CMD:-uvicorn}
|
UVICORN_CMD=${UVICORN_CMD:-uvicorn}
|
||||||
HOST=${HOST:-0.0.0.0}
|
HOST=${HOST:-0.0.0.0}
|
||||||
PORT=${PORT:-8000}
|
PORT=${PORT:-80}
|
||||||
|
|
||||||
exec "${UVICORN_CMD}" backend.app:app --host "${HOST}" --port "${PORT}"
|
exec "${UVICORN_CMD}" backend.app:app --host "${HOST}" --port "${PORT}"
|
||||||
|
|||||||
@ -4,11 +4,11 @@ After=network.target
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Type=simple
|
Type=simple
|
||||||
User=skd
|
User=root
|
||||||
Group=skd
|
Group=root
|
||||||
WorkingDirectory=/opt/sk
|
WorkingDirectory=/opt/sk
|
||||||
EnvironmentFile=/etc/skd/env
|
EnvironmentFile=/etc/skd/env
|
||||||
ExecStart=/opt/sk/.venv/bin/uvicorn backend.app:app --host 0.0.0.0 --port 8000
|
ExecStart=/opt/sk/.venv/bin/uvicorn backend.app:app --host 0.0.0.0 --port 80
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=3
|
RestartSec=3
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user