Local demo
The best way to test InterDiode is to use it locally with Docker Compose, using the compose.yaml file below. It provides a minimal installation of two servers with a unidirectional UDP data transfer. The black instance (connected to the internet) will be available at http://localhost:8881/, the red instance (normally on the internal network) will be available at http://localhost:8882/.
InterDiode provides Docker/OCI images that are available in Docker Hub. It is possible to always use the latest stable tag or to use another service that handles updating Docker images.
This guide explains the setup based on docker-compose, but the installation of docker-compose itself is out of scope of this documentation. To do this, please follow the official install instructions.
Prerequisites for using the demo
Docker and docker-compose installed on the host machine.
A valid license file for InterDiode —— you can use a free demo license.
export EMAIL=<enter_your_email_here>
export NAME=<enter_your_name_here>
curl -o compose.yaml https://interdiode.fr/static/_static/examples/compose.yaml
echo "LICENSE_KEY=$(curl -L https://license.interdiode.fr/v1/license/\?product_id=42\&buyer_name=${NAME}\&buyer_email=${EMAIL}\&order_id=1)" > compose.env
docker compose up -d
Next steps
Once all the containers are running, you can access the web interfaces of both instances at http://localhost:8881/ for the black instance and http://localhost:8882/ for the red instance.
Access to the black instance and create a new account with the “Create account” button. Then, log in with the newly created account.
In the “Administration” section, add the license file that you obtained from the InterDiode team. The license will be automatically applied to the red instance.
Access to the red instance and create a new account with the “Create account” button. Then, log in with the newly created account.
services:
background_black:
command: interdiode-ctl run background -w 4
depends_on:
db_black:
condition: service_healthy
mailpit_black:
condition: service_healthy
migrate_black:
condition: service_completed_successfully
redis_black:
condition: service_healthy
env_file:
- ./compose.env
environment:
- DATABASE_URL=postgresql://interdiode:my-postgres-password@db_black:5432/interdiode_db
- INTERDIODE_MODE=black
- LISTEN_ADDRESS=0.0.0.0:8081
- LOG_DIRECTORY=
- LOG_LEVEL=debug
- REDIS_URL=redis://:my-redis-password@redis_black/1
- RED_DESTINATION_IP=receive_red
- RED_DESTINATION_PORT=9091
- SERVER_BASE_URL=http://localhost:8881/
- SHARED_TRANSFER_KEY=secret_key
- ALLOW_LOCAL_USERS=true
- ALLOW_USER_CREATION=true
- EMAIL_FROM=admin-black@interdiode.example.com
- EMAIL_HOST_URL=smtp://interdiode:password@mailpit_black:1025
- HTTP_REMOTE_GROUPS_HEADER=
- HTTP_REMOTE_USER_HEADER=
- LANGUAGE_CODE=en-us
- REMOTE_USER_DEFAULT_GROUPS=
- REQUIRE_NEW_USER_VALIDATION=false
- TRANSFER_MODE=udp
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- python
- -c
- import os; fd = open('/data/run/interdiode-background.pid'); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()
timeout: 5s
image: interdiode/interdiode:latest
restart: always
volumes:
- ./files/black:/data/files
- ./transfers/black:/data/transfers
- ./logs/black:/data/logs
- ./tmp/black:/data/tmp
background_red:
command: interdiode-ctl run background -w 4
depends_on:
db_red:
condition: service_healthy
mailpit_red:
condition: service_healthy
migrate_red:
condition: service_completed_successfully
redis_red:
condition: service_healthy
env_file:
- ./compose.env
environment:
- DATABASE_URL=postgresql://interdiode:my-postgres-password@db_red:5432/interdiode_db
- INTERDIODE_MODE=red
- LISTEN_ADDRESS=0.0.0.0:8082
- LOG_DIRECTORY=
- LOG_LEVEL=debug
- REDIS_URL=redis://:my-redis-password@redis_red/1
- RED_DESTINATION_IP=receive_red
- RED_DESTINATION_PORT=9091
- SERVER_BASE_URL=http://localhost:8882/
- SHARED_TRANSFER_KEY=secret_key
- ALLOW_LOCAL_USERS=true
- ALLOW_USER_CREATION=true
- EMAIL_FROM=admin-red@interdiode.example.com
- EMAIL_HOST_URL=smtp://interdiode:password@mailpit_red:1025
- HTTP_REMOTE_GROUPS_HEADER=
- HTTP_REMOTE_USER_HEADER=
- LANGUAGE_CODE=en-us
- REMOTE_USER_DEFAULT_GROUPS=
- REQUIRE_NEW_USER_VALIDATION=false
- TRANSFER_MODE=udp
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- python
- -c
- import os; fd = open('/data/run/interdiode-background.pid'); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()
timeout: 5s
image: interdiode/interdiode:latest
restart: always
volumes:
- ./files/red:/data/files
- ./transfers/red:/data/transfers
- ./logs/red:/data/logs
- ./tmp/red:/data/tmp
beat_black:
command: interdiode-ctl run beat
depends_on:
db_black:
condition: service_healthy
mailpit_black:
condition: service_healthy
migrate_black:
condition: service_completed_successfully
redis_black:
condition: service_healthy
env_file:
- ./compose.env
environment:
- DATABASE_URL=postgresql://interdiode:my-postgres-password@db_black:5432/interdiode_db
- INTERDIODE_MODE=black
- LISTEN_ADDRESS=0.0.0.0:8081
- LOG_DIRECTORY=
- LOG_LEVEL=debug
- REDIS_URL=redis://:my-redis-password@redis_black/1
- RED_DESTINATION_IP=receive_red
- RED_DESTINATION_PORT=9091
- SERVER_BASE_URL=http://localhost:8881/
- SHARED_TRANSFER_KEY=secret_key
- ALLOW_LOCAL_USERS=true
- ALLOW_USER_CREATION=true
- EMAIL_FROM=admin-black@interdiode.example.com
- EMAIL_HOST_URL=smtp://interdiode:password@mailpit_black:1025
- HTTP_REMOTE_GROUPS_HEADER=
- HTTP_REMOTE_USER_HEADER=
- LANGUAGE_CODE=en-us
- REMOTE_USER_DEFAULT_GROUPS=
- REQUIRE_NEW_USER_VALIDATION=false
- TRANSFER_MODE=udp
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- python
- -c
- import os; fd = open('/data/run/interdiode-beat.pid'); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()
timeout: 5s
image: interdiode/interdiode:latest
restart: always
volumes:
- ./files/black:/data/files
- ./transfers/black:/data/transfers
- ./logs/black:/data/logs
- ./tmp/black:/data/tmp
beat_red:
command: interdiode-ctl run beat
depends_on:
db_red:
condition: service_healthy
mailpit_red:
condition: service_healthy
migrate_red:
condition: service_completed_successfully
redis_red:
condition: service_healthy
env_file:
- ./compose.env
environment:
- DATABASE_URL=postgresql://interdiode:my-postgres-password@db_red:5432/interdiode_db
- INTERDIODE_MODE=red
- LISTEN_ADDRESS=0.0.0.0:8082
- LOG_DIRECTORY=
- LOG_LEVEL=debug
- REDIS_URL=redis://:my-redis-password@redis_red/1
- RED_DESTINATION_IP=receive_red
- RED_DESTINATION_PORT=9091
- SERVER_BASE_URL=http://localhost:8882/
- SHARED_TRANSFER_KEY=secret_key
- ALLOW_LOCAL_USERS=true
- ALLOW_USER_CREATION=true
- EMAIL_FROM=admin-red@interdiode.example.com
- EMAIL_HOST_URL=smtp://interdiode:password@mailpit_red:1025
- HTTP_REMOTE_GROUPS_HEADER=
- HTTP_REMOTE_USER_HEADER=
- LANGUAGE_CODE=en-us
- REMOTE_USER_DEFAULT_GROUPS=
- REQUIRE_NEW_USER_VALIDATION=false
- TRANSFER_MODE=udp
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- python
- -c
- import os; fd = open('/data/run/interdiode-beat.pid'); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()
timeout: 5s
image: interdiode/interdiode:latest
restart: always
volumes:
- ./files/red:/data/files
- ./transfers/red:/data/transfers
- ./logs/red:/data/logs
- ./tmp/red:/data/tmp
db_black:
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
- POSTGRES_DB=interdiode_db
- POSTGRES_PASSWORD=my-postgres-password
- POSTGRES_USER=interdiode
- PGDATA=/var/lib/postgresql/data/postgresql
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- pg_isready
- -U
- interdiode
- -d
- interdiode_db
timeout: 5s
image: postgres:18
restart: always
volumes:
- ./postgres/black:/var/lib/postgresql/data/postgresql
db_red:
environment:
- POSTGRES_HOST_AUTH_METHOD=trust
- POSTGRES_DB=interdiode_db
- POSTGRES_PASSWORD=my-postgres-password
- POSTGRES_USER=interdiode
- PGDATA=/var/lib/postgresql/data/postgresql
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- pg_isready
- -U
- interdiode
- -d
- interdiode_db
timeout: 5s
image: postgres:18
restart: always
volumes:
- ./postgres/red:/var/lib/postgresql/data/postgresql
mailpit_black:
environment:
- MP_DATABASE=/tmp/mailpit.db
- MP_DISABLE_VERSION_CHECK=1
- MP_DISABLE_WAL=1
- MP_MAX_MESSAGES=5000
- MP_POP3_AUTH=admin_user:password user:password black_user:password red_user:password interdiode:password
- MP_SMTP_AUTH=admin_user:password user:password black_user:password red_user:password interdiode:password
- MP_SMTP_AUTH_ALLOW_INSECURE=1
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- wget
- --spider
- -q
- http://localhost:8025/
timeout: 5s
image: axllent/mailpit
ports:
- 127.0.0.1:8981:8025
restart: always
mailpit_red:
environment:
- MP_DATABASE=/tmp/mailpit.db
- MP_DISABLE_VERSION_CHECK=1
- MP_DISABLE_WAL=1
- MP_MAX_MESSAGES=5000
- MP_POP3_AUTH=admin_user:password user:password black_user:password red_user:password interdiode:password
- MP_SMTP_AUTH=admin_user:password user:password black_user:password red_user:password interdiode:password
- MP_SMTP_AUTH_ALLOW_INSECURE=1
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- wget
- --spider
- -q
- http://localhost:8025/
timeout: 5s
image: axllent/mailpit
ports:
- 127.0.0.1:8982:8025
restart: always
migrate_black:
command: interdiode-ctl configuration apply --no-input
depends_on:
db_black:
condition: service_healthy
mailpit_black:
condition: service_healthy
redis_black:
condition: service_healthy
env_file:
- ./compose.env
environment:
- DATABASE_URL=postgresql://interdiode:my-postgres-password@db_black:5432/interdiode_db
- INTERDIODE_MODE=black
- LISTEN_ADDRESS=0.0.0.0:8081
- LOG_DIRECTORY=
- LOG_LEVEL=debug
- REDIS_URL=redis://:my-redis-password@redis_black/1
- RED_DESTINATION_IP=receive_red
- RED_DESTINATION_PORT=9091
- SERVER_BASE_URL=http://localhost:8881/
- SHARED_TRANSFER_KEY=secret_key
- ALLOW_LOCAL_USERS=true
- ALLOW_USER_CREATION=true
- EMAIL_FROM=admin-black@interdiode.example.com
- EMAIL_HOST_URL=smtp://interdiode:password@mailpit_black:1025
- HTTP_REMOTE_GROUPS_HEADER=
- HTTP_REMOTE_USER_HEADER=
- LANGUAGE_CODE=en-us
- REMOTE_USER_DEFAULT_GROUPS=
- REQUIRE_NEW_USER_VALIDATION=false
- TRANSFER_MODE=udp
image: interdiode/interdiode:latest
volumes:
- ./files/black:/data/files
- ./transfers/black:/data/transfers
- ./logs/black:/data/logs
- ./tmp/black:/data/tmp
migrate_red:
command: interdiode-ctl configuration apply --no-input
depends_on:
db_red:
condition: service_healthy
mailpit_red:
condition: service_healthy
redis_red:
condition: service_healthy
env_file:
- ./compose.env
environment:
- DATABASE_URL=postgresql://interdiode:my-postgres-password@db_red:5432/interdiode_db
- INTERDIODE_MODE=red
- LISTEN_ADDRESS=0.0.0.0:8082
- LOG_DIRECTORY=
- LOG_LEVEL=debug
- REDIS_URL=redis://:my-redis-password@redis_red/1
- RED_DESTINATION_IP=receive_red
- RED_DESTINATION_PORT=9091
- SERVER_BASE_URL=http://localhost:8882/
- SHARED_TRANSFER_KEY=secret_key
- ALLOW_LOCAL_USERS=true
- ALLOW_USER_CREATION=true
- EMAIL_FROM=admin-red@interdiode.example.com
- EMAIL_HOST_URL=smtp://interdiode:password@mailpit_red:1025
- HTTP_REMOTE_GROUPS_HEADER=
- HTTP_REMOTE_USER_HEADER=
- LANGUAGE_CODE=en-us
- REMOTE_USER_DEFAULT_GROUPS=
- REQUIRE_NEW_USER_VALIDATION=false
- TRANSFER_MODE=udp
image: interdiode/interdiode:latest
volumes:
- ./files/red:/data/files
- ./transfers/red:/data/transfers
- ./logs/red:/data/logs
- ./tmp/red:/data/tmp
receive_red:
command: interdiode-ctl hairgap receive
depends_on:
db_red:
condition: service_healthy
mailpit_red:
condition: service_healthy
migrate_red:
condition: service_completed_successfully
redis_red:
condition: service_healthy
env_file:
- ./compose.env
environment:
- DATABASE_URL=postgresql://interdiode:my-postgres-password@db_red:5432/interdiode_db
- INTERDIODE_MODE=red
- LISTEN_ADDRESS=0.0.0.0:8082
- LOG_DIRECTORY=
- LOG_LEVEL=debug
- REDIS_URL=redis://:my-redis-password@redis_red/1
- RED_DESTINATION_IP=receive_red
- RED_DESTINATION_PORT=9091
- SERVER_BASE_URL=http://localhost:8882/
- SHARED_TRANSFER_KEY=secret_key
- ALLOW_LOCAL_USERS=true
- ALLOW_USER_CREATION=true
- EMAIL_FROM=admin-red@interdiode.example.com
- EMAIL_HOST_URL=smtp://interdiode:password@mailpit_red:1025
- HTTP_REMOTE_GROUPS_HEADER=
- HTTP_REMOTE_USER_HEADER=
- LANGUAGE_CODE=en-us
- REMOTE_USER_DEFAULT_GROUPS=
- REQUIRE_NEW_USER_VALIDATION=false
- TRANSFER_MODE=udp
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- python
- -c
- import os; fd = open('/data/run/interdiode-hairgap.pid'); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()
timeout: 5s
image: interdiode/interdiode:latest
restart: always
volumes:
- ./files/red:/data/files
- ./transfers/red:/data/transfers
- ./logs/red:/data/logs
- ./tmp/red:/data/tmp
redis_black:
command: redis-server --requirepass 'my-redis-password' --save 60 1 --loglevel warning
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- redis-cli
- ping
timeout: 5s
image: redis:alpine
restart: always
redis_red:
command: redis-server --requirepass 'my-redis-password' --save 60 1 --loglevel warning
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- redis-cli
- ping
timeout: 5s
image: redis:alpine
restart: always
send_black:
command: interdiode-ctl hairgap send
depends_on:
db_black:
condition: service_healthy
mailpit_black:
condition: service_healthy
migrate_black:
condition: service_completed_successfully
redis_black:
condition: service_healthy
env_file:
- ./compose.env
environment:
- DATABASE_URL=postgresql://interdiode:my-postgres-password@db_black:5432/interdiode_db
- INTERDIODE_MODE=black
- LISTEN_ADDRESS=0.0.0.0:8081
- LOG_DIRECTORY=
- LOG_LEVEL=debug
- REDIS_URL=redis://:my-redis-password@redis_black/1
- RED_DESTINATION_IP=receive_red
- RED_DESTINATION_PORT=9091
- SERVER_BASE_URL=http://localhost:8881/
- SHARED_TRANSFER_KEY=secret_key
- ALLOW_LOCAL_USERS=true
- ALLOW_USER_CREATION=true
- EMAIL_FROM=admin-black@interdiode.example.com
- EMAIL_HOST_URL=smtp://interdiode:password@mailpit_black:1025
- HTTP_REMOTE_GROUPS_HEADER=
- HTTP_REMOTE_USER_HEADER=
- LANGUAGE_CODE=en-us
- REMOTE_USER_DEFAULT_GROUPS=
- REQUIRE_NEW_USER_VALIDATION=false
- TRANSFER_MODE=udp
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- python
- -c
- import os; fd = open('/data/run/interdiode-hairgap.pid'); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()
timeout: 5s
image: interdiode/interdiode:latest
restart: always
volumes:
- ./files/black:/data/files
- ./transfers/black:/data/transfers
- ./logs/black:/data/logs
- ./tmp/black:/data/tmp
web_black:
command: interdiode-ctl run http
depends_on:
db_black:
condition: service_healthy
mailpit_black:
condition: service_healthy
migrate_black:
condition: service_completed_successfully
redis_black:
condition: service_healthy
env_file:
- ./compose.env
environment:
- DATABASE_URL=postgresql://interdiode:my-postgres-password@db_black:5432/interdiode_db
- INTERDIODE_MODE=black
- LISTEN_ADDRESS=0.0.0.0:8081
- LOG_DIRECTORY=
- LOG_LEVEL=debug
- REDIS_URL=redis://:my-redis-password@redis_black/1
- RED_DESTINATION_IP=receive_red
- RED_DESTINATION_PORT=9091
- SERVER_BASE_URL=http://localhost:8881/
- SHARED_TRANSFER_KEY=secret_key
- ALLOW_LOCAL_USERS=true
- ALLOW_USER_CREATION=true
- EMAIL_FROM=admin-black@interdiode.example.com
- EMAIL_HOST_URL=smtp://interdiode:password@mailpit_black:1025
- HTTP_REMOTE_GROUPS_HEADER=
- HTTP_REMOTE_USER_HEADER=
- LANGUAGE_CODE=en-us
- REMOTE_USER_DEFAULT_GROUPS=
- REQUIRE_NEW_USER_VALIDATION=false
- TRANSFER_MODE=udp
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- python
- -c
- import os; fd = open('/data/run/interdiode-http.pid'); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()
timeout: 5s
image: interdiode/interdiode:latest
ports:
- 127.0.0.1:8881:8081
restart: always
volumes:
- ./files/black:/data/files
- ./transfers/black:/data/transfers
- ./logs/black:/data/logs
- ./tmp/black:/data/tmp
web_red:
command: interdiode-ctl run http
depends_on:
db_red:
condition: service_healthy
mailpit_red:
condition: service_healthy
migrate_red:
condition: service_completed_successfully
redis_red:
condition: service_healthy
env_file:
- ./compose.env
environment:
- DATABASE_URL=postgresql://interdiode:my-postgres-password@db_red:5432/interdiode_db
- INTERDIODE_MODE=red
- LISTEN_ADDRESS=0.0.0.0:8082
- LOG_DIRECTORY=
- LOG_LEVEL=debug
- REDIS_URL=redis://:my-redis-password@redis_red/1
- RED_DESTINATION_IP=receive_red
- RED_DESTINATION_PORT=9091
- SERVER_BASE_URL=http://localhost:8882/
- SHARED_TRANSFER_KEY=secret_key
- ALLOW_LOCAL_USERS=true
- ALLOW_USER_CREATION=true
- EMAIL_FROM=admin-red@interdiode.example.com
- EMAIL_HOST_URL=smtp://interdiode:password@mailpit_red:1025
- HTTP_REMOTE_GROUPS_HEADER=
- HTTP_REMOTE_USER_HEADER=
- LANGUAGE_CODE=en-us
- REMOTE_USER_DEFAULT_GROUPS=
- REQUIRE_NEW_USER_VALIDATION=false
- TRANSFER_MODE=udp
healthcheck:
interval: 60s
retries: 10
test:
- CMD
- python
- -c
- import os; fd = open('/data/run/interdiode-http.pid'); pid=fd.read().strip() ; os.kill(int(pid), 0); fd.close()
timeout: 5s
image: interdiode/interdiode:latest
ports:
- 127.0.0.1:8882:8082
restart: always
volumes:
- ./files/red:/data/files
- ./transfers/red:/data/transfers
- ./logs/red:/data/logs
- ./tmp/red:/data/tmp