Use when deploying the Shiny app to the server, after completing features or fixes, before demos, or when user says /deploy. Triggers on "deploy", "push to server", "update laguna".
| Field | Value |
|---|---|
| Server | laguna.ku.lt |
| SSH user | razinka (passwordless SSH key) |
| Target | /srv/shiny-server/inSTREAMPY |
| Method | scp (rsync is broken on this Windows — missing msys-xxhash-0.dll) |
All commands run from: C:\Users\arturas.baziukas\OneDrive - ku.lt\HORIZON_EUROPE\inSTREAM\instream-py
/srv/shiny-server/inSTREAMPY/
├── app.py ← from app/app.py
├── simulation.py ← from app/simulation.py
├── __init__.py ← from app/__init__.py
├── modules/ ← from app/modules/*.py
├── configs/ ← from configs/*.yaml
├── src/instream/ ← from src/instream/ (simulation engine)
├── data/fixtures/ ← from tests/fixtures/ (example data)
└── restart.txt ← touch to restart Shiny Server
conda run -n shiny python -m pytest tests/ -q --tb=short
Stop if tests fail. Do not deploy broken code.
Show a brief summary of what changed (check git diff --stat if helpful). Ask: "Deploy to laguna.ku.lt? (y/n)"
scp "app/app.py" "app/simulation.py" "app/__init__.py" "[email protected]:/srv/shiny-server/inSTREAMPY/"
scp "app/modules/"*.py "[email protected]:/srv/shiny-server/inSTREAMPY/modules/"
IMPORTANT: Use scp -r "src/instream" (no trailing slash) to copy INTO src/.
A trailing slash creates double-nesting (src/instream/instream/).
ssh [email protected] "rm -rf /srv/shiny-server/inSTREAMPY/src/instream"
scp -r "src/instream" "[email protected]:/srv/shiny-server/inSTREAMPY/src/"
scp "configs/"*.yaml "[email protected]:/srv/shiny-server/inSTREAMPY/configs/"
For each fixture directory, wipe stale files first — scp -r appends
to existing directories and leaves dead files behind. When reach names
change between versions (e.g. example_baltic's v1→v2 rename moved
MainStem → Nemunas), the old CSVs would linger otherwise.
ssh [email protected] "rm -f /srv/shiny-server/inSTREAMPY/data/fixtures/example_a/*.csv /srv/shiny-server/inSTREAMPY/data/fixtures/example_a/Shapefile/*"
scp -r "tests/fixtures/example_a/." "[email protected]:/srv/shiny-server/inSTREAMPY/data/fixtures/example_a/"
ssh [email protected] "rm -f /srv/shiny-server/inSTREAMPY/data/fixtures/example_b/*.csv /srv/shiny-server/inSTREAMPY/data/fixtures/example_b/Shapefile/*"
scp -r "tests/fixtures/example_b/." "[email protected]:/srv/shiny-server/inSTREAMPY/data/fixtures/example_b/"
ssh [email protected] "mkdir -p /srv/shiny-server/inSTREAMPY/data/fixtures/example_baltic/Shapefile && rm -f /srv/shiny-server/inSTREAMPY/data/fixtures/example_baltic/*.csv /srv/shiny-server/inSTREAMPY/data/fixtures/example_baltic/Shapefile/*"
scp -r "tests/fixtures/example_baltic/." "[email protected]:/srv/shiny-server/inSTREAMPY/data/fixtures/example_baltic/"
Note: /. suffix copies directory contents without creating a nested directory.
ssh [email protected] "chmod -R g+r /srv/shiny-server/inSTREAMPY 2>/dev/null; touch /srv/shiny-server/inSTREAMPY/restart.txt"
ssh [email protected] "ls -la /srv/shiny-server/inSTREAMPY/app.py && ls /srv/shiny-server/inSTREAMPY/src/instream/__init__.py && echo 'OK: deploy verified'"
curl -s -o /dev/null -w "HTTP %{http_code}\n" --max-time 20 https://laguna.ku.lt/inSTREAMPY/
Expected: HTTP 200. If you get HTTP 500, read the latest log:
ssh [email protected] "ls -lt /var/log/shiny-server/inSTREAMPY-*.log | head -1 | awk '{print \$NF}' | xargs cat"
Report: files synced, server restarted, structure verified.
$() command substitution — run inner commands separatelycd && command — use full paths or ssh host "command"scp -r "src/instream/" into a target that already has instream/ creates instream/instream/. Use scp -r "src/instream" (no trailing slash) and copy into parent.scp "dir/"* fails on subdirectories. Use scp -r "dir/." to copy contents recursively.chmod -R g+r fails on __pycache__ dirs owned by shiny user. Suppress with 2>/dev/null.data/fixtures/example_a/ on server (not data/example_a/).scp -r "dir/." appends; it does NOT delete files that no longer exist in the source. When reach names change (e.g. example_baltic v1→v2 renamed MainStem→Nemunas), old CSVs linger. Always rm -f *.csv in the target fixture dir before scp. Step 6 does this explicitly.shiny micromamba env on laguna does NOT have pyosmium installed. As of v0.30.0, app/modules/create_model_osm.py guards the import so the app boots anyway — but the Create Model panel's Fetch Rivers / Fetch Water buttons raise RuntimeError: pyosmium not installed on click. To enable OSM fetching on production, SSH in and run micromamba install -n shiny -c conda-forge pyosmium -y directly (the conda solver is sometimes slow; expect 1-3 minutes)./var/log/shiny-server/inSTREAMPY-shiny-<timestamp>-<pid>.log. The latest one has the stack trace of the most recent crash — see Step 8.