- Python 46.8%
- Svelte 39.1%
- JavaScript 11.6%
- CSS 1.7%
- Dockerfile 0.4%
- Other 0.3%
|
|
||
|---|---|---|
| .claude/agents | ||
| .forgejo/workflows | ||
| backend | ||
| deploy | ||
| docs | ||
| frontend | ||
| .env.example | ||
| .env.prod.example | ||
| .gitignore | ||
| Caddyfile | ||
| CHANGELOG.md | ||
| CLAUDE.md | ||
| docker-compose.prod.yml | ||
| docker-compose.yml | ||
| LICENSE | ||
| README.md | ||
| VERSION | ||
RiasDrive
Ton drive. Ton serveur.
Un cloud personnel self-hosted pour l'écosystème RiasNetwork : une alternative à Google Drive et Proton Drive, sur ton propre serveur.
▶ Présentation en 24 secondes (télécharger la vidéo)
FastAPI · PostgreSQL 16 · SvelteKit · PocketID OIDC · OnlyOffice · Docker Compose
Sommaire
- Fonctionnalités
- Démarrage rapide
- Configuration
- Architecture
- Mise en production
- Sécurité
- CI/CD
- Développement et tests
- Licence
Fonctionnalités
| Espaces Perso / Boulot | Deux environnements totalement isolés, un seul toggle pour passer de l'un à l'autre |
| Papiers | Zone dédiée aux PDF administratifs : un document déposé est tagué tout seul par des règles d'auto-tagging (conditions ET/OU, regex protégées contre le ReDoS) |
| Fichiers | Upload (fichiers et dossiers), download, arborescence, renommage, déplacement, actions en masse, favoris, récents, recherche |
| Aperçus | Thumbnails images et vidéos, streaming vidéo (HTTP Range), PDF inline, cache HTTP (ETag/304) |
| Édition | Documents Office dans OnlyOffice Document Server ; dessins Excalidraw (.excalidraw) avec sauvegarde auto et export PNG/SVG |
| Partage interne | Droits read / write / owner entre utilisateurs, notification à la réception |
| Liens publics | Expiration, mot de passe, statistiques de consultation et de téléchargement, page publique sans compte |
| Corbeille | Suppression douce, restauration, purge automatique après 30 jours |
| WebDAV | Montage natif (Dolphin, Finder, Explorateur, rclone) avec tokens dédiés, quota RFC 4331 ; voir docs/webdav.md |
| Notifications | In-app et par email (SMTP) : partage reçu, quota proche de la limite |
| Statistiques | Tableau de bord personnel (stockage, fichiers, partages) et statistiques globales côté admin |
| Administration | Utilisateurs, rôles, quotas |
| Interface | SPA dark mode aux couleurs RiasNetwork, FR / EN, responsive mobile |
Démarrage rapide
Prérequis : Docker avec Compose v2, et un client OIDC déclaré dans PocketID
(client_id, client_secret, redirect URI …/auth/callback).
git clone https://git.riasnetwork.com/RiasNetwork/riasdrive.git
cd riasdrive
cp .env.example .env
# éditer .env : SECRET_KEY (≥ 32 caractères), POSTGRES_PASSWORD,
# credentials OIDC, APP_URL, CORS_ORIGINS
docker compose up -d --build
curl -sf http://localhost:8000/health
# {"status":"ok","service":"riasdrive"}
| URL | Service |
|---|---|
http://localhost:8080 |
Application : SPA et API sur une seule origine (gateway Caddy) |
http://localhost:3000 |
SPA seule, sans proxy |
http://localhost:8000 |
API backend en direct |
http://localhost:8000/docs |
Swagger (si ENABLE_API_DOCS=true) |
Les migrations Alembic s'appliquent automatiquement au démarrage du backend.
Configuration
Toutes les variables sont documentées dans .env.example (dev) et
.env.prod.example (prod). Les principales :
| Variable | Rôle | Défaut |
|---|---|---|
POSTGRES_PASSWORD / DATABASE_URL |
Accès PostgreSQL (même mot de passe dans les deux) | changeme |
SECRET_KEY |
Signature des sessions, jetons OnlyOffice et liens (≥ 32 caractères) | — |
OIDC_ISSUER |
Issuer PocketID | http://10.0.20.31 |
OIDC_CLIENT_ID / OIDC_CLIENT_SECRET |
Client OIDC | — |
OIDC_REDIRECT_URI |
Callback OIDC | https://drive.riasnetwork.com/auth/callback |
OIDC_ALLOW_INSECURE_HTTP |
Autorise un issuer en HTTP (réseau interne uniquement) | false |
APP_URL / FRONTEND_URL |
URL publique de l'app ; FRONTEND_URL vide si même domaine |
https://drive.riasnetwork.com |
CORS_ORIGINS |
Origines autorisées, séparées par , |
https://drive.riasnetwork.com |
TRUSTED_PROXY_CIDRS |
Proxies dont on croit l'IP cliente (anti-brute-force) | — |
STORAGE_PATH |
Dossier des blobs | /data/files |
DEFAULT_QUOTA_BYTES |
Quota d'un nouvel utilisateur | 1 Go (32 Go dans .env.example) |
MAX_UPLOAD_BYTES |
Taille max d'un upload | 2 Go |
TRASH_RETENTION_DAYS |
Rétention de la corbeille | 30 |
ALLOWED_UPLOAD_EXTENSIONS |
Liste blanche d'extensions (vide = pas de filtre) | voir .env.example |
ACCESS_TOKEN_TTL_MINUTES / REFRESH_TOKEN_TTL_DAYS |
Durée de vie des tokens | 30 / 30 |
ONLYOFFICE_ENABLED / ONLYOFFICE_JWT_SECRET / ONLYOFFICE_*_URL |
Intégration OnlyOffice | — |
SMTP_* |
Relais email ; SMTP_HOST vide = emails désactivés |
— |
QUOTA_ALERT_THRESHOLD_WARN / _CRIT |
Seuils d'alerte de quota | 80 % / 95 % |
BOOTSTRAP_ADMIN_EMAIL |
Compte promu admin au premier login | — |
DEV_AUTH_BYPASS |
Dev uniquement : /auth/dev-login et WebDAV anonyme |
false |
Architecture
Cinq services Docker Compose :
┌────────────────── gateway (Caddy :8080) ──────────────────┐
│ │
/api /auth /public /dav /health /onlyoffice/* reste
│ │ │
▼ ▼ ▼
backend (FastAPI :8000) ───────────▶ onlyoffice (DS 9.4) frontend (SPA, sirv :3000)
│
▼
db (PostgreSQL 16) + stockage des blobs (/data/files)
RiasDrive/
├── docker-compose.yml # db, backend, frontend, onlyoffice, gateway
├── docker-compose.prod.yml # override prod : images CI, bind mounts /srv/riasdrive
├── Caddyfile # gateway : routage, CSP, HSTS, anti-framing
├── deploy/backup.sh # sauvegarde DB + blobs avec rétention
├── backend/ # FastAPI async
│ ├── alembic/ # migrations
│ ├── tests/ # suite pytest
│ └── app/
│ ├── api/ # routers REST, WebDAV, OnlyOffice, endpoints publics
│ ├── core/ # config, base, sécurité (JWT, PKCE, CSRF), dépendances
│ ├── models/ # SQLAlchemy
│ ├── schemas/ # Pydantic
│ └── services/ # logique métier
├── frontend/ # SvelteKit SPA (adapter-static), @riasnetwork/ui
│ └── src/
│ ├── routes/ # /login, /drive/*, /share/[token]
│ └── lib/ # client API, composants, stores, i18n
└── docs/ # déploiement, WebDAV, audits, maquettes
Endpoints principaux
| Préfixe | Rôle |
|---|---|
/auth/* |
Login OIDC, callback, refresh, logout, /auth/me |
/api/files, /api/folders |
CRUD fichiers et dossiers |
/api/files/{id}/preview|thumbnail|stream |
Aperçus et streaming |
/api/files/new-doc, /api/files/{id}/text |
Documents vierges (Office, Excalidraw) et contenu éditable |
/api/documents, /api/tags, /api/tag-rules |
Papiers, tags et règles d'auto-tagging |
/api/trash/* |
Corbeille |
/api/shares/*, /api/users/search |
Partage interne |
/api/files/{id}/share-links, /api/share-links/* |
Gestion des liens publics |
/public/share/{token} |
Accès public sans authentification |
/api/notifications, /api/stats |
Notifications et statistiques personnelles |
/api/onlyoffice/* |
Configuration éditeur et callback de sauvegarde OnlyOffice |
/dav/*, /api/webdav/tokens |
WebDAV (Basic auth par token) et gestion des tokens |
/api/admin/* |
Administration |
Mise en production
Le guide complet est dans docs/deploiement-production.md
(préparation de l'hôte, checklist .env, mises à jour, sauvegardes, exploitation,
checklist d'ouverture). En résumé :
# 1. Hôte : dossiers persistants + dépôt
sudo mkdir -p /srv/riasdrive/{db,storage,onlyoffice/data,onlyoffice/lib}
git clone https://git.riasnetwork.com/RiasNetwork/riasdrive /opt/riasdrive
cd /opt/riasdrive && cp .env.prod.example .env
openssl rand -hex 32 # SECRET_KEY, ONLYOFFICE_JWT_SECRET
openssl rand -hex 24 # POSTGRES_PASSWORD
# 2. Lancement avec les images publiées par la CI
C="docker compose -f docker-compose.yml -f docker-compose.prod.yml"
docker login git.riasnetwork.com
$C pull && $C up -d
$C ps # 5 services healthy
curl -sf http://localhost:8080/health
# 3. Mise à jour (le pull n'est pas optionnel)
git pull && $C pull && $C up -d
# 4. Sauvegarde quotidienne (DB puis blobs, rétention 14 jours)
# 0 3 * * * cd /opt/riasdrive && ./deploy/backup.sh >> /var/log/riasdrive-backup.log 2>&1
Le TLS est terminé par le proxy frontal (rias-vm-proxy), qui pointe vers la
gateway et transmet l'IP cliente :
drive.riasnetwork.com {
reverse_proxy rias-lxc-drive:8080 {
header_up X-Real-IP {remote_host}
}
}
Seule la gateway (:8080) est exposée ; backend et frontend sont liés à 127.0.0.1,
PostgreSQL et OnlyOffice ne sont pas publiés. Le premier login avec
BOOTSTRAP_ADMIN_EMAIL (à défaut, le tout premier compte) reçoit le rôle admin.
Garde-fous au démarrage : le backend refuse de démarrer si un secret contient
changeme, siDEV_AUTH_BYPASS=trueavec une URL publique, siCORS_ORIGINS=*, ou si l'issuer OIDC est en HTTP sansOIDC_ALLOW_INSECURE_HTTP.
Sécurité
- OIDC/PKCE S256 avec vérification
nonce/state, validation JWKS stricte - Cookies
HttpOnly/Secure/SameSite=Lax, refresh tokens rotatifs révocables en base - CSRF par double-submit cookie sur toute requête mutante authentifiée par cookie
- Anti-brute-force persisté (mots de passe des liens publics, WebDAV, refresh) derrière détection de l'IP réelle via proxy de confiance
- Tokens WebDAV hashés (SHA-256), tokens de liens publics à haute entropie, mots de passe bcrypt
- Uploads : liste blanche d'extensions, re-détection MIME par magic bytes, SVG/HTML jamais servis inline,
nosniffpartout - Emails : valeurs utilisateur échappées en HTML, CR/LF neutralisés dans les en-têtes SMTP
- Quotas atomiques (verrous de ligne) et limites de taille d'upload
- Conteneurs
cap_drop: ALLavec limites mémoire/pids ; gateway avec CSP sans'unsafe-inline'pour les scripts, HSTS, anti-framing
Audits et suivis : docs/security-audit.md, docs/audit-v1-2026-09-16.md.
CI/CD
Le workflow Forgejo Actions .forgejo/workflows/docker-images.yml
lance la suite pytest contre un Postgres éphémère, puis construit et publie les images :
| Image | Source |
|---|---|
git.riasnetwork.com/riasnetwork/riasdrive-backend |
backend/Dockerfile |
git.riasnetwork.com/riasnetwork/riasdrive-frontend |
frontend/Dockerfile |
| Déclencheur | Tags publiés |
|---|---|
push sur main |
latest, <VERSION>, sha-<commit> |
tag vX.Y.Z |
X.Y.Z, X.Y, latest |
| pull request | build seul, sans push |
Seules les images dont le dossier a changé sont reconstruites (une modification de
VERSION, du workflow ou un tag reconstruit les deux). Aucune image n'est publiée si
un test échoue. Le cache buildx vit dans un package dédié (<image>-cache:buildcache).
Prérequis côté forge : un runner avec le label docker ; optionnellement les secrets
REGISTRY_USER / REGISTRY_PASSWORD (sinon le token automatique du job est utilisé).
Dépendance privée @riasnetwork/ui. Le frontend dépend du kit UI via
git+ssh://git@git.riasnetwork.com:2222/RiasNetwork/rias-ui.git. Le npm ci du
Dockerfile le clone avec une deploy key en lecture seule, passée comme secret
BuildKit (jamais ARG/ENV/COPY, donc absente des couches et du cache).
- CI : créer le secret Forgejo
RIAS_UI_DEPLOY_KEY(dépôt RiasDrive → Paramètres → Actions → Secrets) avec le contenu complet de la clé privée, en-têtesBEGIN/ENDcompris. - Build local :
docker build --secret id=rias_ui_deploy_key,src=$HOME/.ssh/riasdrive_rias-ui_deploy frontend/. Avec Compose, le secret est lu depuis ce même chemin (surchargeable viaRIAS_UI_DEPLOY_KEY_FILE) ; la clé ne se copie jamais dans le dépôt. frontend/known_hosts(public, versionné) épingle les clés du serveur Git ; le build utiliseStrictHostKeyChecking=yes. À régénérer si le serveur change de clés hôte.- Le serveur SSH de Forgejo est joint via
RIAS_UI_SSH_HOST(--build-arg, défaut10.0.20.10) : le DNS public degit.riasnetwork.compointe vers le reverse proxy HTTPS, qui n'expose pas le port 2222. Le runner CI doit atteindre cette adresse.
Rollback : repasser sur un tag précédent (sha-<commit> ou X.Y.Z) dans
docker-compose.prod.yml, puis pull et up -d.
Développement et tests
Avec DEV_AUTH_BYPASS=true, GET /auth/dev-login délivre un token sans passer par PocketID :
TOKEN=$(curl -s http://localhost:8000/auth/dev-login | jq -r .access_token)
curl -s http://localhost:8000/api/files \
-H "Authorization: Bearer $TOKEN" -H "X-Environment: personal"
Tests backend (dans le conteneur, où Postgres et STORAGE_PATH sont accessibles) :
docker compose exec backend pip install -r requirements-dev.txt
docker compose exec -u appuser backend pytest -v
requirements-dev.txt n'ajoute que pytest et n'est jamais installé dans l'image de
production ; -u appuser évite les erreurs de permission sur /data/files.
Repartir de zéro :
docker compose down -v && docker compose up -d --build
Licence
Licence « Jtemmerde tu copie pas » (LICENSE) : tous droits réservés,
copie, modification et redistribution interdites sans autorisation écrite de
RiasNetwork. Les dépendances tierces gardent leurs licences. L'interface repose sur le
kit interne @riasnetwork/ui.
La musique de la vidéo de présentation est une composition originale synthétisée pour l'occasion, sans échantillon tiers.
