{"id":51248942,"url":"https://github.com/cubinet-code/radius-user-portal","last_synced_at":"2026-06-29T06:03:10.224Z","repository":{"id":191781111,"uuid":"685381862","full_name":"cubinet-code/radius-user-portal","owner":"cubinet-code","description":"This flask app is a simple portal for managing radius sessions","archived":false,"fork":false,"pushed_at":"2025-07-03T17:15:24.000Z","size":126,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-03T18:25:35.064Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cubinet-code.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-08-31T05:24:43.000Z","updated_at":"2025-07-03T17:20:33.000Z","dependencies_parsed_at":"2023-08-31T17:56:07.590Z","dependency_job_id":"ef3b9e6f-9cf2-4565-b88a-9c69be059d09","html_url":"https://github.com/cubinet-code/radius-user-portal","commit_stats":null,"previous_names":["cubinet-code/radius-user-portal"],"tags_count":3,"template":false,"template_full_name":null,"purl":"pkg:github/cubinet-code/radius-user-portal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubinet-code%2Fradius-user-portal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubinet-code%2Fradius-user-portal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubinet-code%2Fradius-user-portal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubinet-code%2Fradius-user-portal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cubinet-code","download_url":"https://codeload.github.com/cubinet-code/radius-user-portal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cubinet-code%2Fradius-user-portal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34915002,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-29T02:00:05.398Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-29T06:03:09.508Z","updated_at":"2026-06-29T06:03:10.215Z","avatar_url":"https://github.com/cubinet-code.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Radius Session User Portal\n\n![Alt text](/tests/screenshot.png?raw=true)\n\n## Introduction\n\nThis flask app is a simple portal for managing radius sessions. It is intended to be used with the a Radius Server like a Cisco ISE.\nIt was originaly developed for a Cisco ISE deployment as a custom portal to start Radius sessions for use with a Cisco Secure Firewall Manager (CSFM or FMC). The ISE session then gets replicated via Cisco's PXGrid protocol to the CSFM/FMC. The FMC then uses the session information to allow for user based firewall rules.\n\n## Current functionality\n\n- After login, the user can see his current session, refresh or disconnect it.\n- The user will either be disconnected after the session duration or can disconnect it manually.\n- The session duration can be controlled by the config.py or by radius attributes sent by the radius server.\n- Radius server redundancy is supported with automatic failover.\n- Session managment is server side, Cookies are encrypted and signed.\n- Circuit breaker pattern implemented for RADIUS server failure handling.\n- UUID fallback for missing RADIUS Class attributes to prevent crashes.\n- Robust error handling to prevent server hanging and infinite recursion issues.\n\n## Security Features\n\n- **Input Validation**: Username and password validation according to RADIUS standards (length limits and character restrictions)\n- **CSRF Protection**: Cross-Site Request Forgery protection on all forms using Flask-WTF\n- **Security Headers**: Comprehensive HTTP security headers including CSP, X-Frame-Options, HSTS, and more\n- **IP Validation**: Configurable X-Forwarded-For header validation to prevent IP spoofing attacks\n- **Rate Limiting**: Circuit breaker pattern for RADIUS server failures to prevent DoS attacks\n\n## Dependencies\n\nThe application requires the following Python packages (automatically installed via `requirements.txt`):\n\n- **Flask~=3.1.1** - Web framework\n- **Flask-Session~=0.8.0** - Server-side session management using CacheLib backend\n- **Bootstrap-Flask~=2.5.0** - Bootstrap integration for Flask\n- **APScheduler~=3.11.0** - Background task scheduling for session management\n- **pyrad~=2.4** - RADIUS client library\n- **gunicorn~=23.0.0** - WSGI HTTP Server for production deployment\n- **Flask-WTF~=1.2.1** - CSRF protection and form handling\n- **WTForms~=3.2.1** - Form validation and rendering\n- **cachelib~=0.13.0** - Caching library backend for session storage\n- **flask-talisman~=1.1.0** - Security headers and CSP management\n\n## Installation with Ansible\n\nAn Ansible script has been provided for a simple installation on a Debian based system. It will install all required packages and configure the app to run as a systemd service.\n\nIt will install the app to /opt/radius-user-portal and create a virtual environment in /opt/radius-user-portal/venv.\n\n```bash\n# Clone the code to /opt/radius-user-portal (This location is required by the Ansible script)\ngit clone https://github.com/cubinet-code/radius-user-portal.git\n\n# If you dont have Ansible installed, install it with:\nsudo apt install ansible\n# or\npip install ansible\n\n# Then run the playbook with:\nansible-playbook -i 127.0.0.1, ansible-portal.yaml -e ansible_connection=local\n```\n\nAnsible installs a temporary self signed certificate for testing. You should replace it with your own certificate. Please see below for instructions.\n\nYou also still need to edit config.py to [configure](#required-configuration) the portal itself.\n\n## Renew/Reissue SSL certificate\n\nSSL certificates can only be valid for 365 days. You can renew your certificate with the following command:\n\n```bash\ncreate_server_csr.sh\n```\n\nAfter you receive the certificate file as X.509 PEM encoded file, rename it to server.crt and copy it to the app directory:\n\n```bash\ncp server.cer.example server.cer\n# then restart the service\nsystemctl restart portal.service\n```\n\n## NTP Synchronization\n\nThe user portal uses the local clock to calculate the session duration. It is therefore important that the clock is synchronized with NTP. You can check the status with the following command:\n\n```bash\ntimedatectl status\n```\n\nIf the clock is not synchronized, you can enable NTP with the following command:\n\n```bash\n# Update the NTP server in /etc/systemd/timesyncd.conf\nvi /etc/systemd/timesyncd.conf\n# Then enable NTP\nsudo timedatectl set-ntp true\nsudo timedatectl set-timezone 'Europe/Berlin'\n# Restart the service\nsudo systemctl restart systemd-timesyncd.service\n```\n\n## Manual Installation - Getting the code\n\n```bash\ngit clone https://github.com/cubinet-code/radius-user-portal.git\n```\n\nOptional: If you would like to run as a systemd service please update gunicorn.service with your path:\n\n```bash\ncp portal.example.service portal.service\nvi portal.service\n```\n\nThis will install all required python modules in a virtual environment and enable systemd service if portal.services exists.\n\n```bash\n./install.sh\n```\n\n### Without systemd - Manualy run the app in development mode\n\nThis starts the app in debug mode on your local machine port 8443:\n\n```bash\npython portal.py\n```\n\n### Without systemd - Manualy run the app in production mode\n\nThis starts the app in production mode on a scalable server without debugs:\n\n```bash\n./run.sh\n```\n\nThe service will run by default on port 8443. You can change this in the run.sh or portal.py script.\n\n## Required Configuration\n\nCopy the example configuration file config.example.py and edit it to your needs.\n\n```bash\ncp config.example.py config.py\n```\n\nAs you should run a service dealing with user passwords SSL protected, also copy the OPENSSL configuration file and edit it to your needs:\n\n```bash\ncp server.example.cnf server.cnf\n```\n\nThen issue the CSR (certificate signing request) server.csr for signing by your CA:\n\n```bash\ncreate_server_csr.sh\n```\n\nAfter you receive the certificate file as X.509 PEM encoded file, rename it to server.crt and copy it to the app directory.\n\n```bash\ncp server.cer.example server.cer\n# then restart the service\nsystemctl restart portal.service\n```\n\n## Control the session timout with your radius server\n\nYou can send the following radius attributes from your radius server to control the session duration:\n\n```\nIdle-Timeout = \u003cTimout in seconds\u003e\n# or\nSession-Timeout = \u003cTimout in seconds\u003e\n```\n\n## Configuration file reference\n\n```python\n# Configuration file for the User Portal application\n\n#\n# Radius Parameters\n#\n\n# Local IP address of the server which is used as NAS-IP-Address, default is the first IP address of the server\n# PORTAL_IP = \"192.168.1.100\"\n\n# Radius server IP address and secret\nRADIUS_SERVER = \"192.168.1.101\"\n# Radius secret must match your server\nRADIUS_SECRET = \"radiuskey\"\n# Define a backup server if needed\n# RADIUS_SERVER_BACKUP = \"192.168.1.102\"\n\n# The default session duration below can be overriden by your radius server\n# with a Session-Timeout(27) or Idle-Timeout(28) attribute\nDEFAULT_RADIUS_SESSION_DURATION = 60 * 60 * 4  # 4 hours\n\n# Username character validation pattern for RADIUS compatibility\n# Default includes alphanumeric and common symbols safe for Cisco systems\n# You can customize this pattern based on your RADIUS server requirements\nRADIUS_CHAR_PATTERN = r'^[a-zA-Z0-9!#$%\u0026\\'()*+,./:;=?@_{-]+$'\n\n# Circuit breaker functionality for RADIUS server failures\n# After 5 consecutive RADIUS failures, requests are blocked for 60 seconds\n# These values are hardcoded in portal.py but can be modified if needed:\n# RADIUS_FAILURE_THRESHOLD = 5  # Number of failures before circuit breaker activates\n# RADIUS_BACKOFF_TIME = 60      # Seconds to wait before retrying\n\n#\n# Web Server Parameters\n#\n\n# Flask secret key for signing cookie sessions, please change!\nSECRET_KEY = \"secretkey\"\n# Logo url for the login page\n# LOGO_URL = \"https://www.example.com/logo.png\"\n\n# Use Boostrap assets from local server\nBOOTSTRAP_SERVE_LOCAL = True\n# Where to store the session data - using CacheLib backend (recommended)\nSESSION_TYPE = \"cachelib\"\n# Session storage is configured automatically in portal.py using FileSystemCache\n\n```\n\n### Environment Variables\n\nThe following environment variables can be used to configure the application when running in production:\n\n```bash\n# Server configuration\nPORT=8443                    # Port to bind the server to (default: 8443)\nWORKERS=1                    # Number of gunicorn worker processes (default: 1)\nTHREADS=4                    # Number of threads per worker (default: 4)\nSERVE_HTTP=TRUE              # Run in HTTP mode without SSL (for reverse proxy setups)\nFORWARDED_ALLOW_IPS=127.0.0.1 # IPs allowed to set X-Forwarded-For header (default: 127.0.0.1)\n\n# Example usage:\nexport PORT=8000\nexport WORKERS=2\nexport THREADS=8\nexport SERVE_HTTP=TRUE\nexport FORWARDED_ALLOW_IPS=\"127.0.0.1,10.0.0.1\"  # Multiple IPs separated by commas\n./run.sh\n```\n\n### Security Configuration\n\n#### X-Forwarded-For Header Security\n\n**⚠️ IMPORTANT SECURITY CONSIDERATION**\n\nThe application uses the `X-Forwarded-For` header to determine client IP addresses, which are used for RADIUS authentication and potentially firewall rules. By default, Gunicorn only accepts this header from localhost (127.0.0.1,::1) and strips it from other sources for security, but this can be configured.\n\n**Configuration Options:**\n\n1. **Direct Internet Access**: If the application runs directly on the internet without a proxy:\n   ```bash\n   # Don't set FORWARDED_ALLOW_IPS or set it to empty\n   export FORWARDED_ALLOW_IPS=\"\"\n   ```\n\n2. **Behind a Reverse Proxy**: If using a reverse proxy (nginx, HAProxy, etc.):\n   ```bash\n   # Set to your reverse proxy's IP address\n   export FORWARDED_ALLOW_IPS=\"127.0.0.1,10.0.0.1\"\n   ```\n\n3. **Kubernetes/Container Environments**: Set to the pod network or load balancer IP:\n   ```bash\n   # Example for Kubernetes\n   export FORWARDED_ALLOW_IPS=\"10.244.0.0/16\"\n   ```\n\n**Security Impact:**\n- Incorrect configuration allows attackers to spoof source IPs\n- This could bypass IP-based firewall rules in your network infrastructure\n- Always restrict `FORWARDED_ALLOW_IPS` to trusted proxy servers only\n\n#### Input Validation and Security Features\n\nThe application includes comprehensive security measures:\n\n**Input Validation:**\n- Username length limited to 63 characters (RADIUS standard)\n- Password length limited to 128 characters (RADIUS standard)\n- Character validation: configurable pattern via `RADIUS_CHAR_PATTERN` in config.py\n- Default pattern includes: alphanumeric, ! # $ % \u0026 ' ( ) * + , - . / : ; = ? @ _ { }\n- Returns HTTP 400 Bad Request for invalid inputs instead of 500 errors\n\n**CSRF Protection:**\n- All forms protected with CSRF tokens using Flask-WTF\n- Prevents Cross-Site Request Forgery attacks\n- Automatically enabled in production, disabled in test environment\n\n**Security Headers (via Flask-Talisman):**\n- Content Security Policy (CSP) with nonce-based inline script protection\n- X-Frame-Options: DENY to prevent clickjacking\n- X-Content-Type-Options: nosniff to prevent MIME sniffing\n- Referrer-Policy: strict-origin-when-cross-origin\n- HSTS header for HTTPS connections (max-age=31536000; includeSubDomains)\n- Removed deprecated X-XSS-Protection header (CSP provides better protection)\n\n**Session Security:**\n- Server-side sessions using CacheLib filesystem backend\n- Sessions stored in `flask_session` directory with 500 item threshold\n- Signed and encrypted session cookies\n- Configurable session timeouts via RADIUS attributes\n\n## Troubleshooting\n\nThis section covers common issues and their solutions for the RADIUS User Portal.\n\n### Viewing Logs\n\n#### Systemd Service Logs\n\nIf the portal is running as a systemd service, you can view logs using:\n\n```bash\n# View real-time logs\nsudo journalctl -u portal.service -f\n\n# View logs from the last hour\nsudo journalctl -u portal.service --since \"1 hour ago\"\n\n# View all logs for the portal service\nsudo journalctl -u portal.service --no-pager\n\n# View logs with specific priority (error, warning, info, debug)\nsudo journalctl -u portal.service -p err\n```\n\n### Restarting the Server\n\n#### Systemd Service\n\n```bash\n# Restart the portal service\nsudo systemctl restart portal.service\n\n# Check service status\nsudo systemctl status portal.service\n\n# Stop the service\nsudo systemctl stop portal.service\n\n# Start the service\nsudo systemctl start portal.service\n\n# Reload configuration without restarting\nsudo systemctl reload portal.service\n```\n\n#### Manual Process\n\nIf running manually:\n\n```bash\n# Find the process ID\nps aux | grep portal.py\n\n# Kill the process (replace \u003cPID\u003e with actual process ID)\nkill \u003cPID\u003e\n\n# Or force kill if needed\nkill -9 \u003cPID\u003e\n\n# Restart manually\ncd /opt/radius-user-portal\n./run.sh\n```\n\n#### Docker/Container\n\n```bash\n# Restart container\ndocker restart \u003ccontainer-name\u003e\n\n# In Kubernetes\nkubectl rollout restart deployment/portal\n```\n\n### Common Issues and Solutions\n\n#### 1. Server Hanging or Becoming Unresponsive\n\n**Symptoms:**\n\n- Browser shows \"page taking too long to respond\"\n- Application becomes unresponsive\n- High CPU usage\n\n**Solutions:**\n\n```bash\n# Check system resources\ntop\nhtop\nfree -h\n\n# Restart the service\nsudo systemctl restart portal.service\n\n# Check for errors in logs\nsudo journalctl -u portal.service -p err --since \"1 hour ago\"\n```\n\n#### 2. RADIUS Authentication Failures\n\n**Symptoms:**\n\n- Users cannot log in\n- \"Authentication failed\" messages\n- RADIUS timeout errors\n- Message \"RADIUS servers temporarily unavailable\" (circuit breaker activated)\n\n**Solutions:**\n\n```bash\n# Test RADIUS connectivity\n# Install radclient if not available: sudo apt install freeradius-utils\necho \"User-Name=testuser,User-Password=testpass\" | radclient -x \u003cRADIUS_SERVER\u003e:1812 auth \u003cRADIUS_SECRET\u003e\n\n# Check RADIUS server configuration in config.py\ngrep -E \"RADIUS_SERVER|RADIUS_SECRET\" /opt/radius-user-portal/config.py\n\n# Check network connectivity\nping \u003cRADIUS_SERVER\u003e\ntelnet \u003cRADIUS_SERVER\u003e 1812\n\n# Check if circuit breaker is activated (check recent logs for failure patterns)\nsudo journalctl -u portal.service --since \"30 minutes ago\" | grep -i \"radius.*timeout\\|radius.*error\\|temporarily unavailable\"\n\n# If circuit breaker is active, wait 60 seconds or restart the service to reset failure count\nsudo systemctl restart portal.service\n```\n\n**Note:** The application includes a circuit breaker mechanism that temporarily blocks RADIUS requests after 5 consecutive failures to prevent overwhelming failed RADIUS servers. This automatically resets after 60 seconds or when the service is restarted.\n\n#### 3. SSL Certificate Issues\n\n**Symptoms:**\n\n- Browser security warnings\n- SSL handshake failures\n- Certificate expired errors\n\n**Solutions:**\n\n```bash\n# Check certificate validity\nopenssl x509 -in /opt/radius-user-portal/server.cer -text -noout | grep -E \"Not Before|Not After\"\n\n# Verify certificate and key match\nopenssl x509 -noout -modulus -in /opt/radius-user-portal/server.cer | openssl md5\nopenssl rsa -noout -modulus -in /opt/radius-user-portal/server.key | openssl md5\n\n# Regenerate certificate if needed\ncd /opt/radius-user-portal\n./create_server_csr.sh\n```\n\n#### 4. Session Management Issues\n\n**Symptoms:**\n\n- Sessions not persisting\n- Unexpected logouts\n- Session duration problems\n- KeyError exceptions related to missing RADIUS attributes\n\n**Solutions:**\n\n```bash\n# Check session storage permissions\nls -la /opt/radius-user-portal/flask_session/\n\n# Clear session data\nsudo rm -rf /opt/radius-user-portal/flask_session/*\n\n# Check NTP synchronization\ntimedatectl status\n\n# Restart the service\nsudo systemctl restart portal.service\n\n# Check logs for missing RADIUS Class attribute warnings\nsudo journalctl -u portal.service | grep -i \"no class attribute\\|generated session id\"\n```\n\n**Note:** The application now gracefully handles missing RADIUS Class attributes by generating UUID-based session IDs as fallbacks, preventing crashes from incomplete RADIUS responses.\n\n#### 5. High Memory Usage or Memory Leaks\n\n**Symptoms:**\n\n- Gradually increasing memory usage\n- Out of memory errors\n- System slowdown\n\n**Solutions:**\n\n```bash\n# Monitor memory usage\nwatch -n 5 'free -h; ps aux | grep portal.py'\n\n# Restart the service regularly (add to cron if needed)\nsudo systemctl restart portal.service\n\n# Check for memory leaks in logs\nsudo journalctl -u portal.service | grep -i \"memory\\|oom\\|killed\"\n```\n\n#### 6. Permission Issues\n\n**Symptoms:**\n\n- File access errors\n- Permission denied messages\n- Service fails to start\n\n**Solutions:**\n\n```bash\n# Check file permissions\nls -la /opt/radius-user-portal/\n\n# Fix ownership if needed\nsudo chown -R www-data:www-data /opt/radius-user-portal/\n\n# Fix permissions\nsudo chmod 755 /opt/radius-user-portal/\nsudo chmod 644 /opt/radius-user-portal/*.py\nsudo chmod 600 /opt/radius-user-portal/config.py\nsudo chmod 600 /opt/radius-user-portal/server.key\n```\n\n#### 7. Input Validation and Security Errors\n\n**Symptoms:**\n\n- HTTP 400 Bad Request errors during login\n- \"Username contains invalid characters\" messages\n- \"Username/Password too long\" messages\n- CSRF token missing errors\n\n**Solutions:**\n\n```bash\n# Check if inputs meet validation requirements\n# Username: max 63 chars, only alphanumeric + @._-\n# Password: max 128 chars\n\n# Check logs for validation errors\nsudo journalctl -u portal.service | grep -i \"validation\\|csrf\\|bad request\"\n\n# For CSRF errors, ensure:\n# - Forms are properly rendered with CSRF tokens\n# - Session cookies are being set correctly\n# - No JavaScript modifying forms without CSRF tokens\n\n# Check session storage permissions\nls -la /opt/radius-user-portal/flask_session/\nsudo chown -R www-data:www-data /opt/radius-user-portal/flask_session/\n```\n\n**Note:** The application includes comprehensive input validation and CSRF protection. Validation errors return HTTP 400 instead of 500 for better security and user experience.\n\n### Performance Monitoring\n\n#### Check Application Performance\n\n```bash\n# Monitor process resources\nps aux | grep portal.py\n\n# Check network connections\nnetstat -tulpn | grep :8443\n\n# Monitor disk space\ndf -h\n\n# Check system load\nuptime\n```\n\n#### Enable Debug Mode (Development Only)\n\nFor debugging purposes, you can enable debug mode by modifying the configuration:\n\n```python\n# In config.py, add:\nDEBUG = True\n```\n\n**Warning:** Never enable debug mode in production as it can expose sensitive information.\n\n### Getting Help\n\n1. **Check the logs first** - Most issues can be diagnosed from the log output\n2. **Verify configuration** - Ensure all settings in `config.py` are correct\n3. **Test connectivity** - Verify network access to RADIUS servers\n4. **Check system resources** - Ensure adequate CPU, memory, and disk space\n5. **Review recent changes** - Consider any recent configuration or system changes\n\nIf you continue to experience issues after following these troubleshooting steps, please check the project's GitHub repository for known issues and solutions.\n\n## Kubernetes example manifest\n\n```yaml\n---\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: portal\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app.kubernetes.io/instance: portal\n      app.kubernetes.io/name: portal\n  template:\n    metadata:\n      labels:\n        app.kubernetes.io/instance: portal\n        app.kubernetes.io/name: portal\n    spec:\n      containers:\n        - env:\n            - name: PORT # Set desired tcp www port\n              value: \"8000\"\n            - name: SERVE_HTTP # Causes the server to startup in http mode for reverse proxy operation\n              value: \"TRUE\"\n            - name: FORWARDED_ALLOW_IPS # Restrict X-Forwarded-For header to trusted sources\n              value: \"10.244.0.0/16\"  # Example: Kubernetes pod network CIDR\n          image: ghcr.io/cubinet-code/radius-user-portal:latest\n          imagePullPolicy: Always\n          name: portal\n          ports:\n            - containerPort: 8000\n              name: http\n              protocol: TCP\n          volumeMounts:\n            - name: server-config # Mount config file from a configmap\n              mountPath: /opt/radius-user-portal/config.py\n              subPath: config.py\n          resources: {}\n          securityContext: {}\n      securityContext:\n        runAsUser: 1000\n      volumes:\n        - name: server-config # Mount config file from a configmap\n          configMap:\n            name: server-config\n            items:\n              - key: config.py\n                path: config.py\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcubinet-code%2Fradius-user-portal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcubinet-code%2Fradius-user-portal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcubinet-code%2Fradius-user-portal/lists"}