7 Commits

Author SHA1 Message Date
Oscar Krause
8f5f6b8341 fixed debian dependencies 2025-05-15 10:18:09 +02:00
Oscar Krause
de63b32825 fixed pacman dependencies 2025-05-15 10:16:01 +02:00
Oscar Krause
5781029893 finished migration 2025-05-15 10:14:10 +02:00
Oscar Krause
ff8dd3f694 fixes 2025-05-15 10:11:45 +02:00
Oscar Krause
c083acb7ff moved from josepy to pyjwt 2025-05-15 09:24:35 +02:00
Oscar Krause
59bcbd6008 fixed pacman dependency 2025-05-15 08:01:55 +02:00
Oscar Krause
3c239da307 migrate from "python-jose" to "python3-josepy" since it is no longer supported on future releases of debian/ubuntu 2025-05-15 07:59:18 +02:00
6 changed files with 27 additions and 199 deletions

View File

@@ -1,11 +0,0 @@
# https://packages.debian.org/hu/
fastapi==0.115.11
uvicorn[standard]==0.32.0
pyjwt==2.10.1
cryptography==43.0.0
python-dateutil==2.9.0
sqlalchemy==2.0.40
markdown==3.7
python-dotenv==1.0.1
jinja2==3.1.6
httpx==0.28.1

View File

@@ -175,9 +175,9 @@ test:apt:
- debian:trixie-slim # EOL: t.b.a.; "python3-jose" not available, but "python3-josepy" or "python3-jwt"
- debian:bookworm-slim # EOL: June 06, 2026
- debian:bullseye-slim # EOL: June 06, 2026
- ubuntu:24.04 # EOL: April 2036 (Noble Numbat)
- ubuntu:25.04 # EOL: January 2026 (Plucky Puffin); "python3-jose" not available, but "python3-josepy" or "python3-jwt"
- ubuntu:25.10 # EOL: July 2026 (Questing Quokka);
- ubuntu:24.04 # EOL: April 2036
- ubuntu:24.10 # EOL: t.b.a.; "python3-jose" not available, but "python3-josepy" or "python3-jwt"
- ubuntu:25.04 # EOL: t.b.a.; "python3-jose" not available, but "python3-josepy" or "python3-jwt"
needs:
- job: build:apt
artifacts: true
@@ -250,7 +250,7 @@ semgrep-sast:
test_coverage:
# extends: test
image: python:3.13-slim-trixie
image: python:3.12-slim-bookworm
allow_failure: true
stage: test
rules:

View File

@@ -1,4 +1,4 @@
FROM python:3.13-alpine
FROM python:3.12-alpine
ARG VERSION
ARG COMMIT=""

165
README.md
View File

@@ -4,13 +4,13 @@ Minimal Delegated License Service (DLS).
> [!warning] Branch support
> FastAPI-DLS Version 1.x supports up to **`17.x`** releases. \
> FastAPI-DLS Version 2.x is backwards compatible to `17.x` and supports **`18.x`**, **`19.x`**, releases in combination
> with [gridd-unlock-patcher](https://git.collinwebdesigns.de/vgpu/gridd-unlock-patcher).
> FastAPI-DLS Version 2.x is backwards compatible to `17.x` and supports **`18.x`** releases in combination
> with [gridd-unlock-patcher](https://git.collinwebdesigns.de/oscar.krause/gridd-unlock-patcher).
> Other combinations of FastAPI-DLS and Driver-Branches may work but are not tested.
> [!note] Compatibility
> Compatibility tested with official NLS 2.0.1, 2.1.0, 3.1.0, 3.3.1, 3.4.0. **For Driver compatibility
> see [compatibility matrix](#vgpu-software-compatibility-matrix)**.
> Compatibility tested with official NLS 2.0.1, 2.1.0, 3.1.0, 3.3.1, 3.4.0. For Driver compatibility
> see [compatibility matrix](#vgpu-software-compatibility-matrix).
This service can be used without internet connection.
Only the clients need a connection to this service on configured port.
@@ -18,6 +18,7 @@ Only the clients need a connection to this service on configured port.
**Official Links**
* https://git.collinwebdesigns.de/oscar.krause/fastapi-dls (Private Git)
* https://gitea.publichub.eu/oscar.krause/fastapi-dls (Public Git)
* https://hub.docker.com/r/collinwebdesigns/fastapi-dls (Docker-Hub `collinwebdesigns/fastapi-dls:latest`)
*All other repositories are forks! (which is no bad - just for information and bug reports)*
@@ -328,7 +329,6 @@ Packages are available here:
Successful tested with (**LTS Version**):
- **Debian 13 (Trixie)** (EOL: June 30, 2028)
- **Debian 12 (Bookworm)** (EOL: June 06, 2026)
- *Ubuntu 22.10 (Kinetic Kudu)* (EOL: July 20, 2023)
- *Ubuntu 23.04 (Lunar Lobster)* (EOL: January 2024)
@@ -413,141 +413,7 @@ acme.sh --issue -d example.com \
After first success you have to replace `--issue` with `--renew`.
## Nginx Reverse Proxy (experimental)
- This guide is written for Debian/Ubuntu systems, other may work, but you have to do your setup on your own
- Uvicorn does no longer serve requests directly
- NGINX is used as HTTP & HTTPS entrypoint
- Assumes you already have set up webserver certificate and private-key
**Install Nginx Webserver**
```shell
apt-get install nginx-light
```
**Remove default vhost**
```shell
rm /etc/nginx/sites-enabled/default
```
**Create fastapi-dls vhost**
<details>
<summary>`/etc/nginx/sites-available/fastapi-dls`</summary>
```
upstream dls-backend {
server 127.0.0.1:8000; # must match dls listen port
}
server {
listen 443 ssl http2 default_server;
listen [::]:443 ssl http2 default_server;
root /var/www/html;
index index.html;
server_name _;
ssl_certificate "/etc/fastapi-dls/cert/webserver.crt";
ssl_certificate_key "/etc/fastapi-dls/cert/webserver.key";
ssl_session_cache shared:SSL:1m;
ssl_session_timeout 10m;
ssl_protocols TLSv1.3 TLSv1.2;
# ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305";
# ssl_ciphers PROFILE=SYSTEM;
ssl_prefer_server_ciphers on;
location / {
# https://www.uvicorn.org/deployment/
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
proxy_buffering off;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://dls-backend$request_uri;
}
location = /-/health {
access_log off;
add_header 'Content-Type' 'application/json';
return 200 '{\"status\":\"up\",\"service\":\"nginx\"}';
}
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
root /var/www/html;
index index.html;
server_name _;
location /leasing/v1/lessor/shutdown {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://dls-backend/leasing/v1/lessor/shutdown;
}
location / {
return 301 https://$host$request_uri;
}
}
```
</details>
**Enable and test vhost**
```shell
ln -s /etc/nginx/sites-available/fastapi-dls /etc/nginx/sites-enabled/fastapi-dls
nginx -t
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful
```
**Override default fastapi-dls systemd service**
```shell
mkdir /etc/systemd/system/fastapi-dls.service.d
```
<details>
<summary>`/etc/systemd/system/fastapi-dls.service.d/override.conf`</summary>
```
[Service]
ExecStart=
ExecStart=uvicorn main:app \
--env-file /etc/fastapi-dls/env \
--host 127.0.0.1 --port 8000 \
--app-dir /usr/share/fastapi-dls/app \
--proxy-headers
```
</details>
**Run**
```shell
systemctl daemon-reload
service nginx start
service fastapi-dls start
```
# Configuration (Service)
# Configuration
| Variable | Default | Usage |
|------------------------|----------------------------------------|------------------------------------------------------------------------------------------------------|
@@ -670,8 +536,7 @@ Shows current runtime environment variables and their values.
**`GET /-/config/root-certificate`**
Returns the Root-Certificate Certificate which is used.
This is required for patching `nvidia-gridd` on `18.x`, `19.x` releases.
Returns the Root-Certificate Certificate which is used. This is required for patching `nvidia-gridd` on 18.x releases.
**`GET /-/readme`**
@@ -882,16 +747,14 @@ The error message can safely be ignored (since we have no license limitation :P)
# vGPU Software Compatibility Matrix
<details>
<summary>Successfully tested with this package versions: Show Table</summary>
<summary>Show Table</summary>
Successfully tested with this package versions.
| FastAPI-DLS Version | vGPU Suftware | Driver Branch | Linux vGPU Manager | Linux Driver | Windows Driver | Release Date | EOL Date |
|---------------------|:-------------:|:-------------:|--------------------|--------------|----------------|--------------:|--------------:|
| `2.x` | `19.0` | **R580** | `580.65.05` | `580.65.06` | `580.88` | August 2025 | July 2028 |
| `2.x` | `18.4` | **R570** | `570.172.07` | `570.172.08` | `573.48` | July 2025 | March 2026 |
| | `18.3` | **R570** | `570.158.02` | `570.158.01` | `573.36` | June 2025 | |
| | `18.2` | **R570** | `570.148.06` | `570.148.08` | `573.07` | May 2025 | |
| | `18.1` | **R570** | `570.133.08` | `570.133.07` | `572.83` | April 2025 | |
| | `18.0` | **R570** | `570.124.03` | `570.124.06` | `572.60` | March 2025 | |
| `2.x` | `18.1` | **R570** | `570.133.08` | `570.133.07` | `572.83` | April 2025 | March 2026 |
| | `18.0` | **R570** | `570.124.03` | `570.124.06` | `572.60` | March 2025 | March 2026 |
| `1.x` & `2.x` | `17.6` | **R550** | `550.163.02` | `550.63.01` | `553.74` | April 2025 | June 2025 |
| | `17.5` | | `550.144.02` | `550.144.03` | `553.62` | January 2025 | |
| | `17.4` | | `550.127.06` | `550.127.05` | `553.24` | October 2024 | |
@@ -899,7 +762,7 @@ The error message can safely be ignored (since we have no license limitation :P)
| | `17.2` | | `550.90.05` | `550.90.07` | `552.55` | June 2024 | |
| | `17.1` | | `550.54.16` | `550.54.15` | `551.78` | March 2024 | |
| | `17.0` | **R550** | `550.54.10` | `550.54.14` | `551.61` | February 2024 | |
| `1.x` | `16.11` | **R535** | `535.261.04` | `535.261.03` | `539.41` | July 2025 | July 2026 |
| `1.x` | `16.10` | **R535** | `535.247.02` | `535.247.01` | `539.28` | April 2025 | July 2026 |
| `1.x` | `15.4` | **R525** | `525.147.01` | `525.147.05` | `529.19` | June 2023 | December 2023 |
| `1.x` | `14.4` | **R510** | `510.108.03` | `510.108.03` | `514.08` | December 2022 | February 2023 |
@@ -925,6 +788,6 @@ Special thanks to:
- `Krutav Shah` who wrote the [vGPU_Unlock Wiki](https://docs.google.com/document/d/1pzrWJ9h-zANCtyqRgS7Vzla0Y8Ea2-5z2HEi4X75d2Q/)
- `Wim van 't Hoog` for the [Proxmox All-In-One Installer Script](https://wvthoog.nl/proxmox-vgpu-v3/)
- `mrzenc` who wrote [fastapi-dls-nixos](https://github.com/mrzenc/fastapi-dls-nixos)
- `electricsheep49` who wrote [gridd-unlock-patcher](https://git.collinwebdesigns.de/vgpu/gridd-unlock-patcher)
- `electricsheep49` who wrote [gridd-unlock-patcher](https://git.collinwebdesigns.de/oscar.krause/gridd-unlock-patcher)
And thanks to all people who contributed to all these libraries!

View File

@@ -5,8 +5,8 @@ from contextlib import asynccontextmanager
from datetime import datetime, timedelta, UTC
from hashlib import sha256
from json import loads as json_loads, dumps as json_dumps
from os import getenv as env, listdir
from os.path import join, dirname, isfile, isdir, exists
from os import getenv as env
from os.path import join, dirname
from textwrap import wrap
from uuid import uuid4
@@ -14,7 +14,6 @@ from dateutil.relativedelta import relativedelta
from dotenv import load_dotenv
from fastapi import FastAPI
from fastapi.requests import Request
from fastapi.staticfiles import StaticFiles
from fastapi.responses import Response, RedirectResponse, StreamingResponse
import jwt
from sqlalchemy import create_engine
@@ -50,7 +49,6 @@ LEASE_RENEWAL_PERIOD = float(env('LEASE_RENEWAL_PERIOD', 0.15))
LEASE_RENEWAL_DELTA = timedelta(days=int(env('LEASE_EXPIRE_DAYS', 90)), hours=int(env('LEASE_EXPIRE_HOURS', 0)))
CLIENT_TOKEN_EXPIRE_DELTA = relativedelta(years=12)
CORS_ORIGINS = str(env('CORS_ORIGINS', '')).split(',') if (env('CORS_ORIGINS')) else [f'https://{DLS_URL}']
DRIVERS_DIR = env('DRIVERS_DIR', None)
DT_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ'
PRODUCT_MAPPING = ProductMapping(filename=join(dirname(__file__), 'static/product_mapping.json'))
@@ -101,9 +99,6 @@ async def lifespan(_: FastAPI):
config = dict(openapi_url=None, docs_url=None, redoc_url=None) # dict(openapi_url='/-/openapi.json', docs_url='/-/docs', redoc_url='/-/redoc')
app = FastAPI(title='FastAPI-DLS', description='Minimal Delegated License Service (DLS).', version=VERSION, lifespan=lifespan, **config)
if DRIVERS_DIR is not None:
app.mount('/-/static-drivers', StaticFiles(directory=str(DRIVERS_DIR), html=False), name='drivers')
app.debug = DEBUG
app.add_middleware(
CORSMiddleware,
@@ -212,25 +207,6 @@ async def _manage(request: Request):
return Response(response, media_type='text/html', status_code=200)
@app.get('/-/drivers/{directory:path}', summary='* List drivers directory')
async def _drivers(request: Request, directory: str | None):
if DRIVERS_DIR is None:
return Response(status_code=404, content=f'Variable "DRIVERS_DIR" not set.')
path = join(DRIVERS_DIR, directory)
if not exists(path) and not isfile(path):
return Response(status_code=404, content=f'Resource "{path}" not found!')
content = [{
"type": "file" if isfile(f'{path}/{_}') else "folder" if isdir(f'{path}/{_}') else "unknown",
"name": _,
"link": f'/-/static-drivers/{directory}{_}',
} for _ in listdir(path)]
return Response(content=json_dumps({"directory": path, "content": content}), media_type='application/json', status_code=200)
@app.get('/-/origins', summary='* Origins')
async def _origins(request: Request, leases: bool = False):
session = sessionmaker(bind=db)()

View File

@@ -1,8 +1,8 @@
fastapi==0.116.1
uvicorn[standard]==0.35.0
fastapi==0.115.12
uvicorn[standard]==0.34.2
pyjwt==2.10.1
cryptography==45.0.6
cryptography==44.0.3
python-dateutil==2.9.0
sqlalchemy==2.0.43
markdown==3.8.2
python-dotenv==1.1.1
sqlalchemy==2.0.41
markdown==3.8
python-dotenv==1.1.0