Chapters: 

Install Flask on Redhat (repo available)

sudo dnf install python3-flask

🚀 Run Flask App (No pip needed)

  1. Save the app.py somewhere (e.g., /home/tux/transferdepot/app.py)

  2. Run it directly:

python3 /home/tux/transferdepot/app.py

Or set FLASK_APP and use the built-in CLI:

export FLASK_APP=app.py
flask run --host=0.0.0.0 --port=8080

📍 Flask RPM Notes on RHEL 8

  • Package: python3-flask

  • Installed location: /usr/lib/python3.6/site-packages/flask/

  • Installed with all dependencies (Werkzeug, Jinja2, etc.)

  • Managed by dnf, not pip = easy maintenance in air-gapped setup

Define two Routes

| Route                  | Method | Description                                                      |
| ---------------------- | ------ | ---------------------------------------------------------------- |
| `/upload`              | POST   | Accepts file upload (requires `Authorization: Bearer SECRET123`) |
| `/download/<filename>` | GET    | Downloads a file from the upload folder                          |

 

This is our basic app.py - before customization with two routes: upload, download

from flask import Flask, request, send_from_directory
import os

app = Flask(__name__)
UPLOAD_FOLDER = '/opt/transferdepot/uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

@app.route('/upload', methods=['POST'])
def upload():
    token = request.headers.get('Authorization')
    if token != 'Bearer SECRET123':
        return 'Unauthorized', 401
    file = request.files['file']
    filepath = os.path.join(UPLOAD_FOLDER, file.filename)
    file.save(filepath)
    return 'File uploaded successfully', 200

@app.route('/download/<filename>', methods=['GET'])
def download(filename):
    return send_from_directory(UPLOAD_FOLDER, filename)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

 

How to Run

python3 /home/tux/transferdepot/app.py

Or use Flask CLI:

export FLASK_APP=/home/tux/transferdepot/app.py
flask run --host=0.0.0.0 --port=8080

 

First customization:

Add Zones

/opt/transferdepot/
├── logs/
└── zones/
    ├── MSE/
    ├── MP/
    ├── TTCS/
    └── RS2/

Assumption: Each directory is used for both uploads and downloads within that zone — file goes in, file gets picked up later from the same spot.

(Optional) - Add /wormhole Endpoint 

  • A fun (and secure) route for transferring files between zones in a special manner (perhaps a "faster" or "VIP" route). This could be a unique endpoint for certain high-priority transfers.

Updated app.py with Zone-Based Logic

from flask import Flask, request, send_from_directory, abort
import os

app = Flask(__name__)
UPLOAD_ROOT = '/opt/transferdepot/uploads'
ZONES = ['MSE', 'MP', 'TTCS', 'RS2']

# Make sure zone folders exist
for zone in ZONES:
    os.makedirs(os.path.join(UPLOAD_ROOT, zone), exist_ok=True)

@app.route('/upload/<zone>', methods=['POST'])
def upload(zone):
    if zone not in ZONES:
        return 'Invalid zone', 400

    token = request.headers.get('Authorization')
    if token != f'Bearer {zone}123':
        return 'Unauthorized', 401

    if 'file' not in request.files:
        return 'No file part', 400

    file = request.files['file']
    save_path = os.path.join(UPLOAD_ROOT, zone, file.filename)
    file.save(save_path)
    return 'File uploaded to zone successfully', 200

@app.route('/download/<zone>/<filename>', methods=['GET'])
def download(zone, filename):
    if zone not in ZONES:
        abort(404)
    return send_from_directory(os.path.join(UPLOAD_ROOT, zone), filename)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

🚀 The upload and download were eventually removed because I couldn't figure out what they were used for. It didn't work. We can put them back in for a good reason, but not because they used to be there. 

Tests

Test Upload (from same machine or Frodo)

curl -X POST http://localhost:8080/upload/MSE/dropoff \
  -H "Authorization: Bearer MSE123" \
  -F "file=@myfile.txt"

 

Test Download

curl -O http://localhost:8080/download/MSE/pickup/b0b.txt

Result:

  • secret.txt should download to current directory

  • activity.jsonl gets a log entry

 

Current State

  • TransferDepot app (app.py) is built and ready.                                                      ✅                 

    • Basic routes for upload and download are in place.                                        ✅ 

    • Zone-based directories (dropoff, pickup) are being created on the fly.     ✅ 

    • Logging is active, storing each file transfer in activity.jsonl.                      ✅ 

    • Authentication via bearer tokens (Bearer <zone>123).

 

Next Steps  -- TBD --  after demo and approval --

Here are a few things we can add with ease:

1. More Robust Security (Optional)

  • Stronger token handling: Instead of using hardcoded Bearer <zone>123, we could introduce a more flexible method of handling authentication — perhaps with a shared secrets file or token generation system.

  • IP whitelisting: Ensure that only trusted machines/servers can interact with the TransferDepot.

2. Add /status Endpoint (Optional)

  • Show the current status of the TransferDepot, such as:

    • Total number of files uploaded.

    • Size of current transfer directories.

    • Last 10 logs (for quick checks).

    • Zone status (available dropoff/pickup spaces).

3. Advanced Logging (Optional)

  • Currently, the app logs transfers to a single activity.jsonl. We can:

    • Expand logging to log failed attempts, errors, etc.

    • Set up file rotation to prevent activity.jsonl from growing too large.

    • Store logs separately per zone, if you want more detailed analysis per zone.

4. Add /wormhole Endpoint (Optional)

  • A fun (and secure) route for transferring files between zones in a special manner (perhaps a "faster" or "VIP" route). This could be a unique endpoint for certain high-priority transfers.

5. Systemd Integration

  • Turn the app into a systemd service so it starts automatically when the machine boots up. This would ensure TransferDepot runs persistently without needing manual python3 app.py every time.

Example systemd service file:

[Unit]
Description=TransferDepot Service
After=network.target

[Service]
User=tux
WorkingDirectory=/home/tux/transferdepot
ExecStart=/usr/bin/python3 /home/tux/transferdepot/app.py
Restart=always

[Install]
WantedBy=multi-user.target

 

6. Testing and Monitoring (Optional)

  • Use curl to run tests across zones and check the logs.

  • Monitor performance, especially as file sizes increase, to see if you hit any memory or performance issues with large uploads.