Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Nothing is COPY'd into the image — the Dockerfile clones from GitHub.
# This file is kept as a safeguard in case a COPY is added later.

# Secrets — never bake certs or keys into the image
secrets/

# OS
.DS_Store
Thumbs.db
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,4 @@ experiments/
# Local databases
NAS_Database/
Django_database/
.claudeignore
87 changes: 87 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# ============================================================
# SpikesortingLabHub — Production Image
#
# Self-contained: downloads the repo from GitHub so anyone can
# reproduce this image without needing the local source tree.
# ============================================================

FROM ubuntu:24.04

ENV DEBIAN_FRONTEND=noninteractive

# ------------------------------------------------------------
# 1. System packages
# ------------------------------------------------------------
RUN apt-get update && apt-get upgrade -y --no-install-recommends
RUN apt-get install -y --no-install-recommends \
python3 \
python3-venv \
python3-pip \
build-essential \
libpq-dev \
openssl \
ca-certificates \
curl \
git \
nodejs \
npm \
wget \
unzip \
&& rm -rf /var/lib/apt/lists/*

# ------------------------------------------------------------
# 2. Download repository (docker branch) and unpack
# ------------------------------------------------------------
WORKDIR /app
RUN wget -q https://github.com/UserFriendlySpikesorting/SpikesortingLabHub-server/archive/refs/heads/developing_branch.zip \
&& unzip -q developing_branch.zip \
&& mv SpikesortingLabHub-server-developing_branch/* . \
&& rm -rf developing_branch.zip SpikesortingLabHub-server-developing_branch

# ------------------------------------------------------------
# 3. Set up Python virtual environment and install requirements
# ------------------------------------------------------------
RUN python3 -m venv /app/venv
RUN /app/venv/bin/pip install --no-cache-dir -r requirements.txt

# Install SpikesortingLabHub-CLI (patch setup.py for Python 3.12)
RUN wget https://github.com/UserFriendlySpikesorting/SpikesortingLabHub-CLI/archive/refs/heads/main.zip \
&& unzip main.zip \
&& sed -i 's|3.13|3.12|' SpikesortingLabHub-CLI-main/setup.py \
&& /app/venv/bin/pip install --no-cache-dir SpikesortingLabHub-CLI-main/

ENV PATH="/app/venv/bin:$PATH"

# ------------------------------------------------------------
# 4. Build the React frontend
# my-app/build/ is gitignored so it must be compiled here.
# ------------------------------------------------------------
RUN cd my-app && npm ci --omit=dev && npm run build

# ------------------------------------------------------------
# 5. Placeholder directories for bind mounts
# Docker Compose overlays the real host paths at runtime.
# /data ← trurnasdata (read-only NAS database)
# /django_db ← persistentdata (Django SQLite DB + logs)
# /experiments ← binary recording files (read-only)
# ------------------------------------------------------------
RUN mkdir -p /data /app/django_db /app/experiments /app/secrets

# ------------------------------------------------------------
# 6. Entrypoint — already in the repo after download.
# Runs pre-flight checks, collectstatic, migrate, then Gunicorn.
# ------------------------------------------------------------
RUN chmod +x /app/entrypoint.sh
ENTRYPOINT ["/app/entrypoint.sh"]

# ------------------------------------------------------------
# 7. Expose ports
# 9000 — plain HTTP
# 9443 — HTTPS (Gunicorn with --certfile / --keyfile)
# ------------------------------------------------------------
EXPOSE 9000 9443

# ------------------------------------------------------------
# 8. Default command — passed to entrypoint.sh via exec "$@".
# ------------------------------------------------------------
CMD ["gunicorn", "-c", "gunicorn.conf.py", "labhub.wsgi:application"]
108 changes: 108 additions & 0 deletions INSTRUCTIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
# SpikesortingLabHub — TrueNAS Deployment Instructions

Steps tested on the test rig. Replicate these exactly on the main TrueNAS.

> **Path difference:** test rig used `user_home`, main TrueNAS uses `users`.
> Every path below already reflects the main TrueNAS convention.

---

## 1. Enable SSH on TrueNAS

TrueNAS UI → System → Services → start **SSH** and set it to auto-start.

---

## 2. Copy the init script from your Mac to TrueNAS

Run from your Mac terminal (not SSH):

```bash
scp /Users/kajalpatel/SpikesortingLabHub-server/truenas_init.sh \
kajal@128.164.33.182:/mnt/root_data_storage/users/kajal/
```

---

## 3. SSH into TrueNAS

```bash
ssh truenas_admin@128.164.33.182
```

---

## 4. Move the script into the sslh folder

```bash
sudo cp /mnt/root_data_storage/users/kajal/truenas_init.sh \
/mnt/root_data_storage/users/sslh/truenas_init.sh

sudo chmod +x /mnt/root_data_storage/users/sslh/truenas_init.sh
```

---

## 5. Test-run the script manually

```bash
sudo /mnt/root_data_storage/users/sslh/truenas_init.sh
```

Check the log it generates:

```bash
cat /mnt/root_data_storage/users/sslh/sslh_init.log
```

---

## 6. Pull the Docker image and start the container (first time only)

```bash
docker pull ikajalpatel21/spikesorting-labhub-latestimg:latest

export DJANGO_SECRET_KEY="$(cat /mnt/root_data_storage/users/sslh/secrets/django_secret.key)"

docker compose -f /mnt/root_data_storage/users/sslh/docker-compose.yml up -d
```

> If `secrets/django_secret.key` does not exist yet, generate it first:
> ```bash
> mkdir -p /mnt/root_data_storage/users/sslh/secrets
> openssl rand -hex 50 > /mnt/root_data_storage/users/sslh/secrets/django_secret.key
> chmod 600 /mnt/root_data_storage/users/sslh/secrets/django_secret.key
> ```

---

## 7. Verify the container is running

```bash
docker ps
docker logs spikesorting-labhub-server-spikesorting-labhub-1
```

Open in browser: `https://128.164.33.182:9443`
(self-signed cert warning is expected — click through)

---

## 8. Register the init script in TrueNAS UI

System → Advanced Settings → Init/Shutdown Scripts → **Add**

| Field | Value |
|---------|---------------------------------------------------------|
| Type | Script |
| Script | `/mnt/root_data_storage/users/sslh/truenas_init.sh` |
| When | Pre Init |
| Timeout | 30 |

---

## What happens on every reboot after this

1. TrueNAS kernel starts → ZFS pool mounts automatically
2. Pre Init script runs → verifies/creates bind-mount directories → bind-mounts experiments and trurnasdata
3. Docker daemon starts → `restart: unless-stopped` brings the container back up with all mounts in place
Loading