diff --git a/.env.example b/.env.example
index fee4edc9b50cdd0e52b40847367f90dd6cb2a5f2..04d48965ea9875de6da3794f857b5a65791b6b0e 100644
--- a/.env.example
+++ b/.env.example
@@ -14,4 +14,4 @@ HASURA_GRAPHQL_ADMIN_SECRET=my_hasura_password
 HASURA_LISTEN_PORT=8765
 
 # === GATEWAY
-GATEWAY_LISTEN_PORT=3000
\ No newline at end of file
+SUBMIT_GATEWAY_LISTEN_PORT=3000
\ No newline at end of file
diff --git a/.env.prod.example b/.env.prod.example
index 75a375e5d56b795552299b94aa4d3ae6106443b7..58b9fb5a847871d9a970e36a6b15df2248a69d6b 100644
--- a/.env.prod.example
+++ b/.env.prod.example
@@ -10,6 +10,7 @@ KUBO_DOMAIN=datapod.coinduf.eu
 KUBO_WEBSOCKET_DOMAIN=websocket.datapod.coinduf.eu
 KUBO_GATEWAY_DOMAIN=gateway.datapod.coinduf.eu
 KUBO_GATEWAY_SUBDOMAIN=pagu.re
+SUBMIT_GATEWAY_LISTEN_PORT=3000
 
 # configure the node boot
 DATAPOD_BOOT=bafyreih4jspnqnsd4o3sdqv7c765uyylhtlh5majjw6aq6clilkq7tmqey
\ No newline at end of file
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
index def34aea7a68384887e41142ced1d7775b9be4e0..6f01fa0fc856a25edb6ae8c74a2ce294091957d0 100644
--- a/docker-compose.prod.yml
+++ b/docker-compose.prod.yml
@@ -12,7 +12,7 @@ services:
       POSTGRES_PASSWORD: ${DB_PASSWORD}
       POSTGRES_DB: ${DB_DATABASE}
     healthcheck:
-      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d postgres"]
+      test: ['CMD-SHELL', 'pg_isready -U ${DB_USER} -d postgres']
       interval: 1s
 
   # ------
@@ -23,7 +23,7 @@ services:
         condition: service_healthy
     restart: always
     ports:
-      - "127.0.0.1:${HASURA_LISTEN_PORT}:8080"
+      - '127.0.0.1:${HASURA_LISTEN_PORT}:8080'
     environment:
       HASURA_GRAPHQL_DATABASE_URL: postgres://${DB_USER}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE}
       HASURA_GRAPHQL_ENABLE_CONSOLE: true
@@ -43,7 +43,7 @@ services:
       - 127.0.0.1:4002:4002
       # public gateway
       - 127.0.0.1:${KUBO_GATEWAY_PORT}:8080
-      - "[::1]:${KUBO_GATEWAY_PORT}:8080"
+      - '[::1]:${KUBO_GATEWAY_PORT}:8080'
       # expose RPC locally to allow access with ssh tunnel
       - 127.0.0.1:5001:5001
     volumes:
@@ -65,8 +65,8 @@ services:
     depends_on:
       kubo:
         condition: service_healthy
-    entrypoint: "ipfs"
-    command: ["--api=/dns/kubo/tcp/5001", "pubsub", "sub", "ddd"]
+    entrypoint: 'ipfs'
+    command: ['--api=/dns/kubo/tcp/5001', 'pubsub', 'sub', 'ddd']
 
   # ------
   datapod:
@@ -77,14 +77,27 @@ services:
       kubo:
         condition: service_healthy
     environment:
-      KUBO_RPC: "http://kubo:5001"
+      KUBO_RPC: 'http://kubo:5001'
       DB_HOST: postgres
       DB_PORT: 5432
       DB_USER: ${DB_USER}
       DB_PASSWORD: ${DB_PASSWORD}
     restart: always
     # use the datapod collector and indexer, start using given IPNS entry
-    command: ["./src/indexer/start.ts", "${DATAPOD_BOOT}"]
+    command: ['./src/indexer/start.ts', '${DATAPOD_BOOT}']
+
+  # ------
+  gateway:
+    image: h30x/duniter-datapod
+    depends_on:
+      kubo:
+        condition: service_healthy
+    ports:
+      - ${SUBMIT_GATEWAY_LISTEN_PORT}:3000
+    environment:
+      KUBO_RPC: 'http://kubo:5001'
+    restart: always
+    command: ['./src/gateway/start.ts']
 
 volumes:
   db_data:
diff --git a/src/gateway/README.md b/src/gateway/README.md
index 2af5a1c0048e766302abd256062407f9c334db82..000031e6723ba6ba53f3790a0a60e2c8cc901977 100644
--- a/src/gateway/README.md
+++ b/src/gateway/README.md
@@ -4,4 +4,19 @@ This gateway is a way for non-p2p clients to submit data to a http endpoint that
 
 It is a stupid gateway that puts all content to local kubo node (but does not pin) and forwards the cid of the first block on pubsub topic.
 
-Since it does not include any protection mechanism because it relies on datapod network security, it is recommanded to limit the incoming network traffic and apply IP-based protections, preventing an attacker to trigger IPFS garbage collection too easily. Or to limit connection to trusted users.
\ No newline at end of file
+Since it does not include any protection mechanism because it relies on datapod network security, it is recommanded to limit the incoming network traffic and apply IP-based protections, preventing an attacker to trigger IPFS garbage collection too easily. Or to limit connection to trusted users.
+
+## Start
+
+Start the gateway with:
+
+```sh
+pnpm exec tsx ./src/gateway/start.ts
+```
+
+## Sumbit data
+
+The data submitted to the gateway should be a JSON-encoded array of strings.
+
+- the first string is the CID of the index request
+- the other strings are base64 blocks of all data (index request, data, images...)
\ No newline at end of file
diff --git a/src/gateway/start.ts b/src/gateway/start.ts
index 0203a4a94ed3685d03d5686f89133799a5a37a95..8610def6c2b4ff7a9d54b73f83ce85d6ca120c0f 100644
--- a/src/gateway/start.ts
+++ b/src/gateway/start.ts
@@ -1,9 +1,11 @@
 import { TOPIC } from '../consts'
 import { kubo } from '../kubo'
-import * as http from 'http'
+import { createServer } from 'http'
+import type { IncomingMessage, ServerResponse } from 'http'
 
-// we could use this hack to allow submitting json data with html form
-// https://systemoverlord.com/2016/08/24/posting-json-with-an-html-form.html
+const port = process.env.SUBMIT_GATEWAY_LISTEN_PORT || 3000
+const host = '127.0.0.1'
+const postgatewayUrl = `http://${host}:${port}`
 const GATEWAY_LANDING_PAGE = `<!DOCTYPE html>
 <html>
 	<head>
@@ -14,16 +16,18 @@ const GATEWAY_LANDING_PAGE = `<!DOCTYPE html>
 	<body>
 		<h1>Datapod Gateway</h1>
         <p>Use POST requests to submit data programatically. Alternatively, you can submit data manually in the form below for testing purpose.</p>
-        <form method="post" action="http://localhost:3000" enctype='text/plain'>
+        <form method="post" action="${postgatewayUrl}" enctype='text/plain'>
             Blocks as base64 json list: 
-            <input type="text" name="blocks" size=100 placeholder="['index request as base64', 'data as base 64', 'optional aditionnal data as base64'...]"/>
+            <input type="text" name="blocks" size=100 placeholder="['index request cid', 'index request as base64', 'data as base 64', 'optional aditionnal data as base64'...]"/>
             <input type="submit" value="Submit" />
         </form>
 	</body>
 </html>
 `
 
-function handleRequest(request: http.IncomingMessage, response: http.ServerResponse<http.IncomingMessage>) {
+// request handler
+function handleRequest(request: IncomingMessage, response: ServerResponse<IncomingMessage>) {
+  // use post requests to submit data
   if (request.method == 'POST') {
     let body = ''
     request.on('data', function (data) {
@@ -64,8 +68,6 @@ function handleRequest(request: http.IncomingMessage, response: http.ServerRespo
   }
 }
 
-const server = http.createServer(handleRequest)
-const port = process.env.GATEWAY_LISTEN_PORT || 3000
-const host = '127.0.0.1'
+const server = createServer(handleRequest)
 server.listen(port)
-console.log(`Listening on http://${host}:${port}`)
+console.log(`Listening on ${postgatewayUrl}`)