vpn integration
This commit is contained in:
@@ -1,66 +0,0 @@
|
||||
FROM python:3.13-slim
|
||||
|
||||
ARG puid=1000
|
||||
ARG pgid=1000
|
||||
ARG debug=false
|
||||
ENV PYTHONUNBUFFERED=1 \
|
||||
PYTHONDONTWRITEBYTECODE=1 \
|
||||
LANG=C.UTF-8 \
|
||||
LC_ALL=C.UTF-8
|
||||
|
||||
|
||||
RUN groupadd -g ${pgid} -o custom_user
|
||||
RUN useradd -m -u ${puid} -g ${pgid} -o -s /bin/bash custom_user
|
||||
|
||||
#RUN apt update && apt install -y gcc graphviz graphviz-dev pkg-config libpq-dev g++ supervisor
|
||||
RUN apt update && apt install -y curl inotify-tools
|
||||
|
||||
# install nodejs 20
|
||||
#RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
|
||||
#RUN apt update && apt install -y nodejs
|
||||
RUN apt-get update && apt-get install -y \
|
||||
ca-certificates \
|
||||
curl \
|
||||
gnupg \
|
||||
inotify-tools \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
RUN mkdir -p /etc/apt/keyrings
|
||||
RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg
|
||||
RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_20.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
|
||||
RUN apt-get update
|
||||
RUN apt-get install nodejs -y
|
||||
|
||||
# install yarn
|
||||
RUN npm install -g yarn
|
||||
|
||||
# setup node dependencies
|
||||
WORKDIR /app/frontend
|
||||
COPY ./frontend/package.json ./package.json
|
||||
RUN yarn install
|
||||
|
||||
WORKDIR /app
|
||||
RUN pip install --upgrade pip
|
||||
|
||||
COPY requirements*.txt ./
|
||||
RUN if [ "$debug" = "true" ] ; then \
|
||||
pip install --no-cache-dir -r requirements-dev.txt ; \
|
||||
else \
|
||||
pip install --no-cache-dir -r requirements-prod.txt ; \
|
||||
fi
|
||||
|
||||
|
||||
#COPY . .
|
||||
|
||||
RUN chown ${puid}:${pgid} /app -R
|
||||
|
||||
USER custom_user
|
||||
|
||||
RUN mkdir -p ~/.ipython/profile_default/
|
||||
RUN echo "c.InteractiveShellApp.extensions = ['autoreload']\nc.InteractiveShellApp.exec_lines = ['%autoreload 2']" > ~/.ipython/profile_default/ipython_config.py
|
||||
|
||||
EXPOSE 8000
|
||||
|
||||
#HEALTHCHECK --interval=30s --timeout=3s \
|
||||
# CMD curl -f http://127.0.0.1:8000/health/ || exit 1
|
||||
|
||||
CMD bash -c "sleep 2 && python manage.py collectstatic --noinput && python manage.py migrate && uvicorn oxpanel.asgi:application --workers 5 --host 0.0.0.0 --port 8000 --lifespan off --loop asyncio --ws websockets"
|
||||
@@ -1,9 +0,0 @@
|
||||
import os
|
||||
|
||||
from celery import Celery
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")
|
||||
app = Celery("app")
|
||||
|
||||
app.config_from_object("django.conf:settings", namespace="CELERY")
|
||||
app.autodiscover_tasks()
|
||||
@@ -60,8 +60,6 @@ INSTALLED_APPS = [
|
||||
'torrent',
|
||||
'watch_party'
|
||||
]
|
||||
if DEBUG:
|
||||
INSTALLED_APPS = ["daphne"] + INSTALLED_APPS
|
||||
|
||||
MIDDLEWARE = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
|
||||
Regular → Executable
+4
-2
@@ -1,10 +1,12 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
APP_DIR="${APP_DIR:-/oxpanel/app}"
|
||||
|
||||
CORES=$(nproc)
|
||||
WORKERS=$((2 * CORES + 1))
|
||||
|
||||
cd /app/frontend && yarn dev &
|
||||
cd /app && python manage.py runserver 0.0.0.0:8000 &
|
||||
cd "${APP_DIR}/frontend" && yarn dev &
|
||||
cd "${APP_DIR}" && python run_uvicorn.py &
|
||||
|
||||
wait -n
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
nodeLinker: node-modules
|
||||
+10
-10
@@ -10,21 +10,21 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mdi/font": "^7.4.47",
|
||||
"@vitejs/plugin-vue": "^5.2.1",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"postcss": "^8.5.2",
|
||||
"postcss-import": "^16.1.0",
|
||||
"@vitejs/plugin-vue": "^6.0.5",
|
||||
"autoprefixer": "^10.4.27",
|
||||
"postcss": "^8.5.8",
|
||||
"postcss-import": "^16.1.1",
|
||||
"postcss-simple-vars": "^7.0.1",
|
||||
"video.js": "^8.21.0",
|
||||
"vite": "^6.1.0"
|
||||
"video.js": "^8.23.7",
|
||||
"vite": "^8.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"events": "^3.3.0",
|
||||
"filesize": "^10.1.6",
|
||||
"filesize": "^11.0.15",
|
||||
"js-cookie": "^3.0.5",
|
||||
"moment": "^2.30.1",
|
||||
"vite-plugin-vuetify": "^2.1.0",
|
||||
"vue": "^3.5.13",
|
||||
"vuetify": "^3.7.12"
|
||||
"vite-plugin-vuetify": "^2.1.3",
|
||||
"vue": "^3.5.32",
|
||||
"vuetify": "^3.12.5"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export default {
|
||||
plugins: {
|
||||
'postcss-import': {},
|
||||
'postcss-simple-vars': {},
|
||||
// 'postcss-simple-vars': {},
|
||||
'autoprefixer': {}
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,9 @@ import Ws from "./ws";
|
||||
import QtWC from "./qtwebchannel.js"
|
||||
|
||||
export function createVue(component, dom_id){
|
||||
return createApp(component).use(Vuetify).use(Ws).use(QtWC).mount(dom_id)
|
||||
return createApp(component)
|
||||
.use(Vuetify)
|
||||
.use(Ws)
|
||||
.use(QtWC)
|
||||
.mount(dom_id)
|
||||
}
|
||||
+1664
-747
File diff suppressed because it is too large
Load Diff
@@ -1,14 +0,0 @@
|
||||
django
|
||||
django-vite
|
||||
django-cors-headers
|
||||
djangorestframework
|
||||
django-filter
|
||||
djangorestframework-simplejwt
|
||||
channels
|
||||
channels_redis
|
||||
pytz
|
||||
transmission-rpc
|
||||
stream-zip
|
||||
anyio
|
||||
websockets
|
||||
uvloop
|
||||
@@ -1,2 +0,0 @@
|
||||
-r requirements-common.txt
|
||||
daphne
|
||||
@@ -1,2 +0,0 @@
|
||||
-r requirements-common.txt
|
||||
uvicorn
|
||||
@@ -0,0 +1,39 @@
|
||||
import os
|
||||
|
||||
import uvicorn
|
||||
|
||||
|
||||
def build_config() -> dict:
|
||||
debug = os.getenv("DEBUG", "true").lower() == "true"
|
||||
|
||||
config = {
|
||||
"host": os.getenv("UVICORN_HOST", "0.0.0.0"),
|
||||
"port": int(os.getenv("UVICORN_PORT", "8000")),
|
||||
"loop": "asyncio",
|
||||
"ws": "websockets",
|
||||
"proxy_headers": True,
|
||||
"forwarded_allow_ips": "*",
|
||||
"log_level": "debug" if debug else "info",
|
||||
"access_log": True
|
||||
}
|
||||
|
||||
if debug:
|
||||
config.update(
|
||||
{
|
||||
"reload": True,
|
||||
"reload_dirs": ["."],
|
||||
"workers": 1,
|
||||
}
|
||||
)
|
||||
else:
|
||||
config.update(
|
||||
{
|
||||
"workers": int(os.getenv("UVICORN_WORKERS", "5")),
|
||||
}
|
||||
)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
uvicorn.run("app.asgi:application", **build_config())
|
||||
@@ -37,6 +37,9 @@ def clean_old_torrents():
|
||||
print(f"delete torrent {torrent.name}")
|
||||
torrent.delete()
|
||||
|
||||
def update_peer_port():
|
||||
transmission_handler.update_vpn_port()
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
task_schedule = {
|
||||
@@ -47,6 +50,10 @@ class Command(BaseCommand):
|
||||
"clean_old_torrents": {
|
||||
"func": clean_old_torrents,
|
||||
"schedule": 5.0
|
||||
},
|
||||
"update_peer_port": {
|
||||
"func": update_peer_port,
|
||||
"schedule": 10.0
|
||||
}
|
||||
}
|
||||
histories = {}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import os
|
||||
|
||||
from django.conf import settings
|
||||
|
||||
import traceback
|
||||
@@ -21,6 +23,24 @@ class Transmission:
|
||||
|
||||
def __init__(self):
|
||||
self.client = Client(**settings.TRANSMISSION)
|
||||
self.update_vpn_port()
|
||||
|
||||
def update_vpn_port(self):
|
||||
"""Lit le port forwarded par Gluetun et met à jour Transmission si nécessaire"""
|
||||
port_file = "/tmp/gluetun/forwarded_port"
|
||||
if os.path.exists(port_file):
|
||||
try:
|
||||
with open(port_file) as f:
|
||||
vpn_port = int(f.read().strip())
|
||||
|
||||
# Récupère le port actuel configuré dans Transmission
|
||||
current_settings = self.client.get_session()
|
||||
if current_settings.peer_port != vpn_port:
|
||||
self.client.set_session(peer_port=vpn_port)
|
||||
# Optionnel: loguer le changement
|
||||
print(f"Transmission peer-port updated to {vpn_port}")
|
||||
except Exception as e:
|
||||
print(f"Error updating Transmission port: {e}")
|
||||
|
||||
def add_torrent(self, file, file_mode="file_object"):
|
||||
match file_mode:
|
||||
@@ -53,6 +73,34 @@ class Transmission:
|
||||
def delete(self, hash_string):
|
||||
return self.client.remove_torrent(hash_string, delete_data=True)
|
||||
|
||||
def get_diagnostics(self):
|
||||
"""
|
||||
Retourne des informations détaillées sur l'état de Transmission et du VPN.
|
||||
Utile pour le debug via le shell Django.
|
||||
"""
|
||||
session = self.client.get_session()
|
||||
|
||||
# 1. Vérification du port VPN (Lecture du fichier Gluetun)
|
||||
port_file = "/tmp/gluetun/forwarded_port"
|
||||
vpn_port = None
|
||||
if os.path.exists(port_file):
|
||||
with open(port_file, "r") as f:
|
||||
vpn_port = f.read().strip()
|
||||
|
||||
# 2. Test de connectivité du port (via l'API Transmission)
|
||||
# Ceci demande à Transmission de vérifier si son port est ouvert sur internet
|
||||
port_is_open = self.client.port_test()
|
||||
|
||||
return {
|
||||
"transmission_version": session.version,
|
||||
"config_peer_port": session.peer_port,
|
||||
"gluetun_forwarded_port": vpn_port,
|
||||
"port_test_success": port_is_open,
|
||||
"download_dir": session.download_dir,
|
||||
"rpc_version": session.rpc_version,
|
||||
"peer_port_random_on_start": session.peer_port_random_on_start,
|
||||
}
|
||||
|
||||
|
||||
transmission_handler = Transmission()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user