nihook-ui/
├── backend/ # Python/Flask Backend
│ ├── api/ # API Routes (Blueprints)
│ ├── auth/ # Auth logic & JWT callbacks
│ ├── models/ # SQLAlchemy Database Models
│ ├── services/ # Business Logic (SSH, etc.)
│ ├── web/ # Frontend serving blueprint
│ ├── __init__.py # Application Factory
│ ├── config.py # Application Configuration
│ ├── extensions.py # Flask Extensions (DB, JWT, Migrate)
│ └── requirements.txt # Backend Dependencies
├── frontend/ # Frontend Source
│ ├── app.ts # Main TypeScript logic
│ ├── schema-builder.ts # Schema builder logic
│ ├── styles.css # Global styles
│ └── *.html # View templates
├── migrations/ # Database Migrations (Alembic)
├── instance/ # Instance-specific files (DB)
├── run.py # Application Entry Point
├── package.json # Frontend Dependencies & Scripts
└── tsconfig.json # TypeScript Configuration
- Python 3.8+
- Node.js & npm
- Podman (remote or local)
Create a virtual environment and install dependencies:
# Create virtual environment
python -m venv venv
source venv/bin/activate # On Windows use `venv\Scripts\activate`
# Install dependencies
pip install -r backend/requirements.txt
# Note: Ensure Flask-Migrate is installed if missing
pip install Flask-MigrateInstall TypeScript dependencies and compile the frontend code:
# Install dependencies
npm install
# Build the frontend (compiles TS -> JS)
npm run build
# Or run in watch mode during development
npm run watchCopy the example environment file to .env:
cp .env.example .envOpen .env and configure your settings (SSH credentials, secret keys, etc.):
# Flask
FLASK_DEBUG=True
DATABASE_URL=sqlite:///containers.db
JWT_SECRET_KEY=your-secret-key
# SSH / Podman Configuration
SSH_HOSTNAME=remote-host.com
SSH_PORT=22
SSH_USERNAME=root
SSH_KEY_FILE=/path/to/private/key
# OR
SSH_PASSWORD=your-password
# Application Paths
NIHOOK_FOLDER=/path/to/nihook
CONTAINER_SCRIPTS_DIR=/path/to/nihook/scriptsInitialize the database using migrations:
# Apply existing migrations
flask db upgrade
# If you make changes to models:
# flask db migrate -m "Description of change"
# flask db upgradeStart the Flask development server:
python app.pyThe application will be available at http://localhost:5000.
The project includes a multi-stage Dockerfile that compiles the TypeScript frontend, sets up the Python runtime, and automatically handles database migrations.
Copy the .env.example file to .env:
cp .env.example .envInside .env, if you are utilizing SSH keys to connect to remote Podman servers, point the SSH_KEY_FILE directly to /app/.ssh/id_rsa. (This corresponds to where the key will be inside the container).
The default is to run NiHook-UI on your local laptop or workstation and to make it ssh into the NiHook server. If you want to run the NiHook-UI container on the NiHook server, start from .env.example-container-localhost and copy it to .env. In this case you need to use ssh, too, to connect from inside the NiHook-UI container to the host.
The database is using SQLite. To avoid data loss when your container stops/starts, create an instance/ folder on your host machine to store the .db file locally safely:
mkdir -p instanceYou can run via the included helper script (just verify the path to your SSH key on your laptop inside the script):
chmod +x podman_run.sh
./podman_run.shOr manually via Podman CLI:
# Build the multi-stage image
podman build -t nihook-ui .
# Run the container
# IMPORTANT: Map your local SSH key to /app/.ssh/id_rsa and append :ro,z
# The ':ro,z' is crucial because it makes it read-only and explicitly tells SELinux to let the container read it.
podman run -d \
--name nihook-ui \
-v /home/YOUR_LOCAL_USER/.ssh/your_key:/app/.ssh/id_rsa:ro,z \
-v $(pwd)/instance:/app/instance:Z \
--env-file .env \
-p 9000:9000 \
nihook-ui- If NiHook-UI runs on you local laptop/workstation navigate to
http://127.0.0.1:9000to access the UI. Don't uselocalhost:5000due to IPv6 setups on modern machines. - If NiHook is running on the NiHook server, then you should use an ssh tunnel to connect. Run
ssh -L9000:localhost:9000 <nihook-serverand then navigate tohttp://127.0.0.1:9000.
GET/POST /login- Login page & authenticationGET/POST /register- Registration page & user creationPOST /logout- Logout current user
GET /- List all containersPOST /- Create new containerGET /<id>- Get container detailsPUT /<id>- Update containerPOST /<id>/start- Start containerPOST /<id>/stop- Stop containerPOST /<id>/restart- Restart containerPOST /<id>/delete- Delete containerGET /<id>/logs- List logsGET /<id>/logs/<filename>- View log file
GET /- List all schemasPOST /- Create new schemaGET /<id>- Get schema detailsPUT /<id>- Update schemaDELETE /<id>- Delete schemaGET /<id>/download- Download schema JSONPOST /create-table- Create table from schema
- JWT Authentication: Secure API endpoints with JSON Web Tokens
- Password Hashing: User passwords are saved securely
- CSRF Protection: Enabled for specific operations
For production, use a proper WSGI server like Gunicorn:
gunicorn -w 4 -b 0.0.0.0:5000 run:app-
SSH Connection Failed:
- Verify SSH credentials in
.env - Ensure the remote server is accessible
- Check that Podman is installed on the remote server
- Verify SSH credentials in
-
Database Issues:
- Delete
containers.dband restart to recreate - Ensure write permissions in the backend directory
- Delete
-
TypeScript Compilation Errors:
- Make sure Node.js is installed
- Check TypeScript version compatibility
Enable debug logging by setting FLASK_DEBUG=1 in your environment.
- Container Logs: View real-time container logs
- Resource Monitoring: CPU, memory, and network usage
- Container Statistics: Historical performance data
- User Roles: Admin, power user, regular user permissions
- Container Templates: Pre-configured container setups
- Multi-VM Support: Manage containers across multiple servers
- Container Networking: Advanced network configuration
- Backup/Restore: Container backup functionality
For issues, questions, or contributions, please open an issue on GitHub.