deployment fixes
This commit is contained in:
+6
-4
@@ -24,10 +24,12 @@ SMTP_TIMEOUT=30
|
||||
SSH_HOST=media-server.example.com
|
||||
SSH_USERNAME=username
|
||||
SSH_PORT=22
|
||||
# In Docker Compose, mount your private key at ./secrets/ssh/id_ed25519
|
||||
# and set this path to /root/.ssh/id_ed25519 inside the backend container.
|
||||
SSH_KEY_FILENAME=/root/.ssh/id_ed25519
|
||||
SSH_KEY_NAME=id_rsa
|
||||
# In Docker Compose, mount ./secrets/ssh to /root/.ssh inside the backend container.
|
||||
# The app uses SSH_KEY_DIRECTORY + SSH_KEY_NAME to build the full key path.
|
||||
SSH_KEY_DIRECTORY=/root/.ssh
|
||||
SSH_KEY_NAME=id_ed25519
|
||||
# Optional legacy override if you want to provide the full path directly.
|
||||
# SSH_KEY_FILENAME=/root/.ssh/id_ed25519
|
||||
# SSH_PASSWORD=optional-password-or-key-passphrase
|
||||
REMOTE_MEDIA_ROOT=/mnt/media
|
||||
# Optional fallback prefix when REMOTE_MEDIA_ROOT mapping is not enough.
|
||||
|
||||
@@ -83,9 +83,12 @@ LOG_LEVEL=INFO
|
||||
SSH_HOST=media-server.example.com
|
||||
SSH_USERNAME=username
|
||||
SSH_PORT=22
|
||||
# In Docker Compose, mount your private key at ./secrets/ssh/id_ed25519
|
||||
# and your host key file at ./secrets/ssh/known_hosts.
|
||||
SSH_KEY_FILENAME=/root/.ssh/id_ed25519
|
||||
# In Docker Compose, mount ./secrets/ssh to /root/.ssh inside the backend container.
|
||||
# The app uses SSH_KEY_DIRECTORY + SSH_KEY_NAME to build the full key path.
|
||||
SSH_KEY_DIRECTORY=/root/.ssh
|
||||
SSH_KEY_NAME=id_ed25519
|
||||
# Optional legacy override if you want to provide the full path directly.
|
||||
# SSH_KEY_FILENAME=/root/.ssh/id_ed25519
|
||||
SSH_PASSWORD=
|
||||
|
||||
REMOTE_MEDIA_ROOT=/srv/media
|
||||
|
||||
+6
-3
@@ -71,9 +71,12 @@ OIDC_CLOCK_SKEW_SECONDS=30
|
||||
SSH_HOST=media-server.example.com
|
||||
SSH_USERNAME=username
|
||||
SSH_PORT=22
|
||||
# In Docker Compose, mount your private key at ./secrets/ssh/id_ed25519
|
||||
# and your host key file at ./secrets/ssh/known_hosts.
|
||||
SSH_KEY_FILENAME=/root/.ssh/id_ed25519
|
||||
# In Docker Compose, mount ./secrets/ssh to /root/.ssh inside the backend container.
|
||||
# The app uses SSH_KEY_DIRECTORY + SSH_KEY_NAME to build the full key path.
|
||||
SSH_KEY_DIRECTORY=/root/.ssh
|
||||
SSH_KEY_NAME=id_ed25519
|
||||
# Optional legacy override if you want to provide the full path directly.
|
||||
# SSH_KEY_FILENAME=/root/.ssh/id_ed25519
|
||||
SSH_PASSWORD=
|
||||
|
||||
REMOTE_MEDIA_ROOT=/srv/media
|
||||
|
||||
@@ -55,7 +55,9 @@ class Settings(BaseSettings):
|
||||
ssh_host: str = ""
|
||||
ssh_username: str = ""
|
||||
ssh_port: int = 22
|
||||
ssh_key_filename: str = str(Path.home() / ".ssh" / "id_rsa")
|
||||
ssh_key_directory: str = str(Path.home() / ".ssh")
|
||||
ssh_key_name: str = "id_rsa"
|
||||
ssh_key_filename: str = "" # legacy direct override (full path)
|
||||
ssh_password: str = ""
|
||||
|
||||
# Remote paths
|
||||
@@ -71,6 +73,12 @@ class Settings(BaseSettings):
|
||||
def path_prefix(self) -> str:
|
||||
return self.remote_path_prefix or ""
|
||||
|
||||
@property
|
||||
def ssh_key_path(self) -> str:
|
||||
if self.ssh_key_filename:
|
||||
return self.ssh_key_filename
|
||||
return str(Path(self.ssh_key_directory) / self.ssh_key_name)
|
||||
|
||||
model_config = {"env_file": ".env", "env_file_encoding": "utf-8", "extra": "ignore"}
|
||||
|
||||
|
||||
|
||||
@@ -50,14 +50,14 @@ def get_ssh_client() -> RemoteSSHClient:
|
||||
settings.ssh_host or "<unset>",
|
||||
settings.ssh_username or "<unset>",
|
||||
settings.ssh_port,
|
||||
settings.ssh_key_filename or "<unset>",
|
||||
settings.ssh_key_path or "<unset>",
|
||||
"set" if settings.ssh_password else "missing",
|
||||
)
|
||||
client = RemoteSSHClient(
|
||||
host=settings.ssh_host,
|
||||
username=settings.ssh_username,
|
||||
port=settings.ssh_port,
|
||||
key_filename=settings.ssh_key_filename or None,
|
||||
key_filename=settings.ssh_key_path or None,
|
||||
password=settings.ssh_password or None,
|
||||
)
|
||||
try:
|
||||
|
||||
@@ -52,6 +52,8 @@ def describe_settings(settings: object) -> dict[str, str]:
|
||||
"ssh_host": getattr(settings, "ssh_host", "") or "<unset>",
|
||||
"ssh_username": getattr(settings, "ssh_username", "") or "<unset>",
|
||||
"ssh_port": str(getattr(settings, "ssh_port", 22) or 22),
|
||||
"ssh_key_directory": getattr(settings, "ssh_key_directory", "") or "<unset>",
|
||||
"ssh_key_name": getattr(settings, "ssh_key_name", "") or "<unset>",
|
||||
"ssh_key_filename": "set" if getattr(settings, "ssh_key_filename", "") else "missing",
|
||||
"ssh_password": "set" if getattr(settings, "ssh_password", "") else "missing",
|
||||
"smtp_host": _sanitize_url(getattr(settings, "smtp_host", "")),
|
||||
|
||||
@@ -9,12 +9,13 @@ services:
|
||||
- .env
|
||||
environment:
|
||||
AUTH_ENABLED: "false"
|
||||
SSH_KEY_FILENAME: /root/.ssh/id_rsa
|
||||
SSH_KEY_DIRECTORY: /root/.ssh
|
||||
SSH_KEY_NAME: ${SSH_KEY_NAME:-id_ed25519}
|
||||
ports:
|
||||
- "8000:8000"
|
||||
volumes:
|
||||
- ./backend:/app/backend
|
||||
- ./secrets/ssh/:/root/.ssh/
|
||||
- ./secrets/ssh:/root/.ssh:ro
|
||||
restart: unless-stopped
|
||||
|
||||
frontend:
|
||||
|
||||
+3
-2
@@ -5,9 +5,10 @@ services:
|
||||
dockerfile: backend/Dockerfile
|
||||
environment:
|
||||
AUTH_ENABLED: "true"
|
||||
SSH_KEY_FILENAME: /root/.ssh/${SSH_KEY_NAME}
|
||||
SSH_KEY_DIRECTORY: /root/.ssh
|
||||
SSH_KEY_NAME: ${SSH_KEY_NAME}
|
||||
volumes:
|
||||
- ./secrets/ssh:/root/.ssh:ro
|
||||
- ${SSH_KEY_DIRECTORY}:/root/.ssh:ro
|
||||
restart: unless-stopped
|
||||
expose:
|
||||
- "8000"
|
||||
|
||||
@@ -127,6 +127,7 @@ Phase 1: Jellyfin media index, SSH-based remote filesystem inspection, server mo
|
||||
- Support OIDC login in the frontend using an OIDC client library, with backend JWT validation for protected API requests.
|
||||
- Provide Docker Compose deployment files at the repository root for production and local development.
|
||||
- Backend Docker deployment should mount a private SSH key and a known_hosts file into the container rather than baking them into the image.
|
||||
- The SSH key configuration should support separate directory/name inputs so Docker Compose can mount an entire `./secrets/ssh` directory into `/root/.ssh` while the app assembles the full key path.
|
||||
- Show Jellyfin media counts for movies, series, and series episodes on the dashboard.
|
||||
- Show dashboard session activity from Jellyfin, including both currently playing sessions and logged-in idle sessions.
|
||||
- Activity rows should include user, media title (or `(idle)`), playback state (`playing`/`paused`/`idle`), and whether transcoding is active.
|
||||
@@ -169,4 +170,4 @@ Phase 1: Jellyfin media index, SSH-based remote filesystem inspection, server mo
|
||||
- 2026-05-03: Confirmed the shared session table should keep the compact overall status summary line above the rows.
|
||||
- 2026-05-03: Updated the dashboard monitoring cards to show 10-minute averages with high/low subtext instead of only the latest sample.
|
||||
- 2026-05-03: Added OIDC/JWT auth support plus root-level Docker Compose deployment files for production and dev workflows.
|
||||
- 2026-05-04: Backend Docker Compose now mounts `./secrets/ssh/id_ed25519` and `./secrets/ssh/known_hosts` into `/root/.ssh` so Paramiko can use a private key and strict host-key checking without baking secrets into the image.
|
||||
- 2026-05-04: Backend Docker Compose now mounts the entire `./secrets/ssh` directory into `/root/.ssh` so Paramiko can use a private key and strict host-key checking without baking secrets into the image.
|
||||
|
||||
Reference in New Issue
Block a user