Merge branch 'master' into database-setup
This commit is contained in:
@@ -3,7 +3,7 @@ FROM mcr.microsoft.com/devcontainers/typescript-node:24-bookworm
|
||||
# Arguments for the non-root user (provided by VS Code remote extensions)
|
||||
ARG USERNAME=node
|
||||
|
||||
# Install system packages required by Tauri on Linux
|
||||
# Install system packages required by Tauri on Linux and packages for VNC/noVNC
|
||||
RUN apt-get update \
|
||||
&& apt-get install -y --no-install-recommends \
|
||||
git \
|
||||
@@ -19,7 +19,17 @@ RUN apt-get update \
|
||||
libxdo-dev \
|
||||
libssl-dev \
|
||||
libayatana-appindicator3-dev \
|
||||
libgdk-pixbuf2.0-dev \
|
||||
librsvg2-dev \
|
||||
xvfb \
|
||||
xauth \
|
||||
dbus-x11 \
|
||||
xfce4 \
|
||||
xfce4-goodies \
|
||||
x11vnc \
|
||||
websockify \
|
||||
python3 \
|
||||
python3-pip \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install rustup and the stable toolchain into the non-root user's home
|
||||
@@ -46,3 +56,23 @@ USER ${USERNAME}
|
||||
RUN cargo install --locked just || true
|
||||
|
||||
WORKDIR /workspace
|
||||
|
||||
# Temporarily switch back to root to install noVNC into /opt (root-owned)
|
||||
USER root
|
||||
|
||||
# clone noVNC so we can proxy VNC over WebSockets (browser access)
|
||||
RUN git clone https://github.com/novnc/noVNC.git /opt/noVNC \
|
||||
&& git clone https://github.com/novnc/websockify.git /opt/noVNC/utils/websockify \
|
||||
&& chown -R ${USERNAME}:${USERNAME} /opt/noVNC
|
||||
|
||||
# Ensure novnc scripts are executable
|
||||
RUN chmod +x /opt/noVNC/utils/novnc_proxy || true
|
||||
|
||||
# Return to the non-root user for the rest of the build
|
||||
USER ${USERNAME}
|
||||
|
||||
# copy the VNC start script (added in devcontainer) and make it executable
|
||||
COPY --chown=${USERNAME}:${USERNAME} start-vnc.sh /workspace/.devcontainer/start-vnc.sh
|
||||
RUN chmod +x /workspace/.devcontainer/start-vnc.sh
|
||||
|
||||
EXPOSE 5900 6080
|
||||
|
||||
@@ -15,5 +15,18 @@ How to use
|
||||
|
||||
Notes
|
||||
- If you need additional system libraries for your distribution, edit `Dockerfile`.
|
||||
- Forwarded port: `5173` (Vite dev server).
|
||||
- `just` is available in the container; run `just` to execute repository tasks.
|
||||
- Forwarded ports:
|
||||
- `5173` (Vite dev server)
|
||||
- `5900` (VNC server - direct VNC connection)
|
||||
- `6080` (noVNC web interface - access via browser)
|
||||
- `just` is available in the container; run `just` to execute repository tasks.
|
||||
|
||||
VNC / noVNC (Remote Desktop)
|
||||
- This devcontainer includes a headless X11 environment with XFCE4 desktop.
|
||||
- To start VNC: Run `just start-vnc` in the terminal
|
||||
- To stop VNC: Run `just stop-vnc`
|
||||
- Access the desktop via:
|
||||
1. **Browser (recommended)**: http://localhost:6080/vnc.html
|
||||
2. **VNC client**: Connect to `localhost:5900` with password `devpass`
|
||||
- Default VNC password: `devpass` (set via `VNC_PASSWORD` environment variable)
|
||||
- If you see "Port 6080 already in use", the noVNC service is already running.
|
||||
|
||||
@@ -10,7 +10,28 @@
|
||||
"extensions": ["rust-lang.rust-analyzer", "esbenp.prettier-vscode", "dbaeumer.vscode-eslint", "nefrob.vscode-just-syntax"]
|
||||
},
|
||||
"postCreateCommand": "corepack enable && corepack prepare pnpm@latest --activate && pnpm install && cd src-tauri && cargo fetch && cd -",
|
||||
"forwardPorts": [5173],
|
||||
"forwardPorts": [5173, 5900, 6080],
|
||||
"portsAttributes": {
|
||||
"5173": {
|
||||
"label": "Vite Dev Server",
|
||||
"onAutoForward": "notify"
|
||||
},
|
||||
"5900": {
|
||||
"label": "VNC Server",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"6080": {
|
||||
"label": "noVNC Web (VNC via Browser)",
|
||||
"protocol": "http"
|
||||
}
|
||||
},
|
||||
"remoteEnv": { "VNC_PASSWORD": "devpass", "DISPLAY": "${localEnv:DISPLAY}" },
|
||||
|
||||
"runArgs": [
|
||||
"-e",
|
||||
"DISPLAY=${localEnv:DISPLAY}"
|
||||
],
|
||||
|
||||
"mounts": [
|
||||
"source=${localWorkspaceFolder},target=/workspace,type=bind,consistency=cached"
|
||||
],
|
||||
|
||||
31
.devcontainer/manual-start-vnc.sh
Executable file
31
.devcontainer/manual-start-vnc.sh
Executable file
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Manual wrapper to start the VNC services on demand.
|
||||
# Use this instead of automatic postStartCommand.
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
ROOT="${SCRIPT_DIR%/.*}/.."
|
||||
|
||||
LOGDIR=/tmp
|
||||
OUT_LOG="$LOGDIR/start-vnc.manual.log"
|
||||
|
||||
echo "Starting VNC services (logs -> $OUT_LOG)"
|
||||
|
||||
# Ensure underlying start script exists
|
||||
if [ ! -x "$SCRIPT_DIR/start-vnc.sh" ] && [ -f "$SCRIPT_DIR/start-vnc.sh" ]; then
|
||||
chmod +x "$SCRIPT_DIR/start-vnc.sh" || true
|
||||
fi
|
||||
|
||||
if [ ! -f "$SCRIPT_DIR/start-vnc.sh" ]; then
|
||||
echo "Error: start-vnc.sh not found in $SCRIPT_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Run the original script in the background and stream logs to the terminal
|
||||
nohup bash "$SCRIPT_DIR/start-vnc.sh" >"$OUT_LOG" 2>&1 &
|
||||
PID=$!
|
||||
echo "start-vnc.sh started with PID $PID"
|
||||
echo "Tailing logs (press Ctrl-C to stop tailing):"
|
||||
sleep 1
|
||||
tail -n +1 -f "$OUT_LOG"
|
||||
104
.devcontainer/start-vnc.sh
Executable file
104
.devcontainer/start-vnc.sh
Executable file
@@ -0,0 +1,104 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# Start a headless X server, a lightweight desktop, x11vnc and noVNC proxy.
|
||||
# Runs as the container user (configured via devcontainer.json remoteUser).
|
||||
|
||||
VNC_PASS=${VNC_PASSWORD:-devpass}
|
||||
VNC_DIR="$HOME/.vnc"
|
||||
mkdir -p "$VNC_DIR"
|
||||
|
||||
if [ ! -f "$VNC_DIR/passwd" ]; then
|
||||
echo "Creating VNC password"
|
||||
x11vnc -storepasswd "$VNC_PASS" "$VNC_DIR/passwd"
|
||||
fi
|
||||
|
||||
# Prefer using an existing X server (host) when available. Set USE_EXISTING_DISPLAY=true
|
||||
# to force using the existing DISPLAY; otherwise, if a host DISPLAY is propagated into the
|
||||
# container (via devcontainer runArgs / mounts), prefer that instead of starting Xvfb.
|
||||
if [ "${USE_EXISTING_DISPLAY:-}" = "true" ] || { [ -n "${DISPLAY:-}" ] && [ -d "/tmp/.X11-unix" ]; }; then
|
||||
echo "Using existing X server on ${DISPLAY:-<unset>} (X11 forwarding to host)"
|
||||
export USE_EXISTING_DISPLAY=true
|
||||
else
|
||||
echo "Prefer Xvfb — starting Xvfb :1"
|
||||
if command -v Xvfb >/dev/null 2>&1; then
|
||||
Xvfb :1 -screen 0 1280x720x24 >/tmp/xvfb.log 2>&1 &
|
||||
export DISPLAY=:1
|
||||
else
|
||||
echo "Warning: Xvfb not available; expecting an X server on DISPLAY"
|
||||
fi
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Starting desktop session (xfce)"
|
||||
# startxfce4 backgrounds itself; if not available fall back to openbox
|
||||
if command -v startxfce4 >/dev/null 2>&1; then
|
||||
startxfce4 >/tmp/xfce4.log 2>&1 &
|
||||
else
|
||||
if command -v openbox-session >/dev/null 2>&1; then
|
||||
openbox-session >/tmp/openbox.log 2>&1 &
|
||||
fi
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
|
||||
echo "Starting x11vnc on ${DISPLAY:-:1}"
|
||||
if [ "${USE_EXISTING_DISPLAY:-}" != "true" ]; then
|
||||
# enable client-side caching for viewers that support it
|
||||
x11vnc -display "${DISPLAY:-:1}" -rfbauth "$VNC_DIR/passwd" -forever -shared -rfbport 5900 -ncache 10 -ncache_cr -bg || true
|
||||
else
|
||||
echo "USE_EXISTING_DISPLAY=true — skipping x11vnc (display forwarded to host)"
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
|
||||
# Locate noVNC installation. Prefer /opt/noVNC, then workspace/noVNC.
|
||||
NOVNC_DIR=""
|
||||
if [ -d /opt/noVNC ]; then
|
||||
NOVNC_DIR="/opt/noVNC"
|
||||
elif [ -d "$PWD/noVNC" ]; then
|
||||
NOVNC_DIR="$PWD/noVNC"
|
||||
# Ensure it's available under /opt for tools that expect it there
|
||||
if [ ! -e /opt/noVNC ]; then
|
||||
mkdir -p /opt
|
||||
ln -s "$NOVNC_DIR" /opt/noVNC || true
|
||||
fi
|
||||
fi
|
||||
|
||||
# Start the noVNC proxy only when we are running an internal VNC server on port 5900
|
||||
if [ -n "$NOVNC_DIR" ] && [ "${USE_EXISTING_DISPLAY:-}" != "true" ]; then
|
||||
echo "Found noVNC at $NOVNC_DIR"
|
||||
echo "Waiting for VNC server on localhost:5900..."
|
||||
ATTEMPTS=0
|
||||
until ss -ltnp | grep -q ':5900' || [ $ATTEMPTS -ge 10 ]; do
|
||||
ATTEMPTS=$((ATTEMPTS+1))
|
||||
sleep 1
|
||||
done
|
||||
|
||||
if ss -ltnp | grep -q ':5900'; then
|
||||
# If port 6080 is already bound, report the owner and skip starting a new proxy.
|
||||
if ss -ltnp | grep -q ':6080'; then
|
||||
echo "Port 6080 already in use. Current listener:"
|
||||
ss -ltnp | egrep ':6080' || true
|
||||
echo "Skipping starting another noVNC proxy to avoid address-in-use errors."
|
||||
else
|
||||
echo "Starting noVNC proxy on port 6080"
|
||||
# Prefer the bundled novnc_proxy script; pass explicit --web and bind address
|
||||
NOVNC_PROXY="$NOVNC_DIR/utils/novnc_proxy"
|
||||
if [ -x "$NOVNC_PROXY" ]; then
|
||||
nohup "$NOVNC_PROXY" --vnc localhost:5900 --listen 0.0.0.0:6080 --web "$NOVNC_DIR" >/tmp/novnc.log 2>&1 &
|
||||
else
|
||||
nohup python3 "$NOVNC_DIR/utils/novnc_proxy" --vnc localhost:5900 --listen 0.0.0.0:6080 --web "$NOVNC_DIR" >/tmp/novnc.log 2>&1 &
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo "VNC server not listening on :5900, skipping noVNC startup. See logs for details."
|
||||
fi
|
||||
else
|
||||
if [ "${USE_EXISTING_DISPLAY:-}" = "true" ]; then
|
||||
echo "Using host X11 forwarding; skipping noVNC/websockify startup."
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "VNC service started. Connect to :5900 or open http://<host>:6080/vnc.html"
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -26,5 +26,5 @@ dist-ssr
|
||||
#pnpm
|
||||
.pnpm-store
|
||||
|
||||
# cargo
|
||||
# target
|
||||
target/
|
||||
|
||||
13
justfile
13
justfile
@@ -17,3 +17,16 @@ db-migrate:
|
||||
|
||||
rm crates/temp.db
|
||||
|
||||
start-vnc:
|
||||
@echo "Run the manual VNC start script"
|
||||
bash .devcontainer/manual-start-vnc.sh
|
||||
|
||||
stop-vnc:
|
||||
@echo "Stop x11vnc and novnc proxy"
|
||||
pkill -f x11vnc || true
|
||||
pkill -f novnc_proxy || true
|
||||
|
||||
dev DISPLAY='1':
|
||||
# Note: this assumes that the VNC server is running and accessible at DISPLAY=:1
|
||||
# Check the start-vnc output for the correct DISPLAY value if you have multiple VNC sessions running
|
||||
DISPLAY=:{{DISPLAY}} pnpm tauri dev
|
||||
|
||||
@@ -28,3 +28,13 @@ migration = { path = "../crates/migration" }
|
||||
thiserror = "1"
|
||||
rust_decimal = "1"
|
||||
uuid = { version = "1", features = ["v4"] }
|
||||
|
||||
[profile.dev]
|
||||
incremental = true
|
||||
|
||||
[profile.release]
|
||||
codegen-units = 1
|
||||
lto = true
|
||||
opt-level = 3
|
||||
# panic = "abort"
|
||||
strip = true
|
||||
|
||||
@@ -22,6 +22,14 @@
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"android": {
|
||||
"autoIncrementVersionCode": false,
|
||||
"minSdkVersion": 24
|
||||
},
|
||||
"iOS": {
|
||||
"minimumSystemVersion": "14.0"
|
||||
},
|
||||
"category": "Finance",
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"icon": [
|
||||
@@ -32,4 +40,4 @@
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user