@ossy/deployment-tools 1.21.0 → 1.21.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## 1.21.2 (2026-05-26)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @ossy/deployment-tools
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## 1.21.1 (2026-05-26)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @ossy/deployment-tools
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
# 1.21.0 (2026-05-26)
|
|
7
23
|
|
|
8
24
|
|
package/README.md
CHANGED
|
@@ -75,7 +75,9 @@ Host ports are auto-assigned starting at `3002`, counting only HTTP services (TC
|
|
|
75
75
|
|
|
76
76
|
#### TCP/UDP service
|
|
77
77
|
|
|
78
|
-
No Caddy block.
|
|
78
|
+
No Caddy block. Containers run with **`--network host`** so game servers bind ports on the EC2 instance directly (avoids Docker bridge DNAT issues for public traffic). The `ports` and `protocol` fields still drive **security group** ingress rules — they are not passed as `-p` mappings.
|
|
79
|
+
|
|
80
|
+
Use this for game servers or any other raw socket protocol.
|
|
79
81
|
|
|
80
82
|
```json
|
|
81
83
|
"services": [
|
|
@@ -85,6 +87,15 @@ No Caddy block. Ports are mapped directly (`HOST:CONTAINER`) and opened in the E
|
|
|
85
87
|
"image": "itzg/minecraft-server",
|
|
86
88
|
"ports": [25565],
|
|
87
89
|
"protocol": "tcp"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "palworld",
|
|
93
|
+
"type": "tcp",
|
|
94
|
+
"image": "thijsvanloef/palworld-server-docker",
|
|
95
|
+
"ports": [
|
|
96
|
+
{ "port": 8211, "protocol": "udp" },
|
|
97
|
+
{ "port": 27021, "protocol": "udp" }
|
|
98
|
+
]
|
|
88
99
|
}
|
|
89
100
|
]
|
|
90
101
|
```
|
|
@@ -94,8 +105,8 @@ No Caddy block. Ports are mapped directly (`HOST:CONTAINER`) and opened in the E
|
|
|
94
105
|
| `name` | Unique service name — Docker container name and systemd unit. |
|
|
95
106
|
| `type` | Must be `"tcp"` to enable this mode. |
|
|
96
107
|
| `image` | Docker image to pull and run. |
|
|
97
|
-
| `ports` |
|
|
98
|
-
| `protocol` | `"tcp"` (default), `"udp"`, or `"both"`. |
|
|
108
|
+
| `ports` | Port numbers (host network) and security group rules. Use a **number** with service-level `protocol`, or `{ "port": 8211, "protocol": "udp" }` per port when protocols differ. |
|
|
109
|
+
| `protocol` | Default for numeric `ports` entries: `"tcp"` (default), `"udp"`, or `"both"`. Ignored when every port is an object with its own `protocol`. Must match what the game image listens on. |
|
|
99
110
|
|
|
100
111
|
**Fixed built-in services** (always present, not configurable via `services`):
|
|
101
112
|
- `ossy-api` — the Ossy API (`ghcr.io/ossy-se/api:latest`, port 3001)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/deployment-tools",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.2",
|
|
4
4
|
"description": "Collection of scripts and tools to aid deployment of containers and static files to Amazon Web Services through GitHub Actions",
|
|
5
5
|
"source": "./src/index.js",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -22,5 +22,5 @@
|
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"jest": "^27.5.1"
|
|
24
24
|
},
|
|
25
|
-
"gitHead": "
|
|
25
|
+
"gitHead": "5747c957d77061c1172a0ac7a6a54d1644986927"
|
|
26
26
|
}
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
* @property {'tcp'} type - marks a raw socket service; bypasses Caddy entirely
|
|
18
18
|
* @property {string} name - unique service name (container + systemd unit)
|
|
19
19
|
* @property {string} image - Docker image (e.g. itzg/minecraft-server)
|
|
20
|
-
* @property {number[]} ports
|
|
21
|
-
* @property {'tcp'|'udp'|'both'} [protocol] - defaults to 'tcp'
|
|
20
|
+
* @property {(number|{port: number, protocol: 'tcp'|'udp'|'both'})[]} ports - host ports + security group rules
|
|
21
|
+
* @property {'tcp'|'udp'|'both'} [protocol] - default for numeric ports; defaults to 'tcp'
|
|
22
22
|
* @property {Record<string,string>=} env - environment variables written to /etc/environment on the EC2 host at boot time; never uploaded to S3
|
|
23
23
|
*
|
|
24
24
|
* @property {string} awsAccountId - Aws account id
|
|
@@ -11,14 +11,38 @@
|
|
|
11
11
|
* @property {'tcp'} type - marks this as a raw TCP/UDP service (no HTTP/Caddy)
|
|
12
12
|
* @property {string} name - unique name, used for container name and systemd unit
|
|
13
13
|
* @property {string} image - Docker image to run
|
|
14
|
-
* @property {number[]} ports
|
|
15
|
-
* @property {'tcp'|'udp'|'both'} [protocol] - defaults to 'tcp'
|
|
14
|
+
* @property {(number|TcpPortEntry)[]} ports - host ports; each entry uses `protocol` or the service default
|
|
15
|
+
* @property {'tcp'|'udp'|'both'} [protocol] - default for numeric ports; defaults to 'tcp'
|
|
16
|
+
*
|
|
17
|
+
* @typedef {Object} TcpPortEntry
|
|
18
|
+
* @property {number} port
|
|
19
|
+
* @property {'tcp'|'udp'|'both'} protocol
|
|
16
20
|
*
|
|
17
21
|
* @typedef {HttpServiceConfig|TcpServiceConfig} ContainerServiceConfig
|
|
18
22
|
*/
|
|
19
23
|
|
|
20
24
|
const BASE_HTTP_PORT = 3002 // 3000 = platform runtime, 3001 = API
|
|
21
25
|
|
|
26
|
+
/**
|
|
27
|
+
* @param {(number|TcpPortEntry)[]} ports
|
|
28
|
+
* @param {'tcp'|'udp'|'both'} defaultProtocol
|
|
29
|
+
* @returns {TcpPortEntry[]}
|
|
30
|
+
*/
|
|
31
|
+
const normalizePortEntries = (ports, defaultProtocol = 'tcp') =>
|
|
32
|
+
ports.map(entry =>
|
|
33
|
+
typeof entry === 'number'
|
|
34
|
+
? { port: entry, protocol: defaultProtocol }
|
|
35
|
+
: { port: entry.port, protocol: entry.protocol ?? defaultProtocol }
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
/** @param {TcpPortEntry} entry */
|
|
39
|
+
const expandSecurityGroupRules = ({ port, protocol }) => {
|
|
40
|
+
if (protocol === 'both') {
|
|
41
|
+
return [{ port, protocol: 'tcp' }, { port, protocol: 'udp' }]
|
|
42
|
+
}
|
|
43
|
+
return [{ port, protocol }]
|
|
44
|
+
}
|
|
45
|
+
|
|
22
46
|
// ---------------------------------------------------------------------------
|
|
23
47
|
// HTTP service — reverse-proxied through Caddy, container listens on port 3000
|
|
24
48
|
// ---------------------------------------------------------------------------
|
|
@@ -80,23 +104,23 @@ ${this.domain} {
|
|
|
80
104
|
}
|
|
81
105
|
|
|
82
106
|
// ---------------------------------------------------------------------------
|
|
83
|
-
// TCP/UDP service — bypasses Caddy,
|
|
84
|
-
//
|
|
107
|
+
// TCP/UDP service — bypasses Caddy, listens on the EC2 host network namespace.
|
|
108
|
+
// Uses --network host so game traffic hits the process directly (no bridge DNAT).
|
|
109
|
+
// Security group ingress still comes from securityGroupPorts below.
|
|
85
110
|
// ---------------------------------------------------------------------------
|
|
86
111
|
|
|
87
112
|
class TcpContainerService {
|
|
88
113
|
constructor({ name, image, ports, protocol = 'tcp' }) {
|
|
89
114
|
this.name = name
|
|
90
115
|
this.image = image
|
|
91
|
-
this.
|
|
92
|
-
this.protocol = protocol // 'tcp' | 'udp' | 'both'
|
|
116
|
+
this.portEntries = normalizePortEntries(ports, protocol)
|
|
93
117
|
}
|
|
94
118
|
|
|
95
119
|
get systemdUnitFile() {
|
|
96
|
-
const
|
|
120
|
+
const portList = this.portEntries.map(({ port, protocol }) => `${port}/${protocol}`).join(', ')
|
|
97
121
|
return `
|
|
98
122
|
[Unit]
|
|
99
|
-
Description=Container service: ${this.name} (
|
|
123
|
+
Description=Container service: ${this.name} (host network, ${portList})
|
|
100
124
|
After=network.target docker.service
|
|
101
125
|
Requires=docker.service
|
|
102
126
|
|
|
@@ -105,8 +129,7 @@ EnvironmentFile=/etc/environment
|
|
|
105
129
|
ExecStartPre=-/usr/bin/docker rm -f ${this.name}
|
|
106
130
|
ExecStartPre=/usr/bin/docker pull ${this.image}
|
|
107
131
|
ExecStart=/usr/bin/docker run --name ${this.name} \\
|
|
108
|
-
--network
|
|
109
|
-
${portMappings} \\
|
|
132
|
+
--network host \\
|
|
110
133
|
--env-file /etc/environment \\
|
|
111
134
|
${this.image}
|
|
112
135
|
ExecStop=/usr/bin/docker stop ${this.name}
|
|
@@ -121,12 +144,9 @@ WantedBy=multi-user.target
|
|
|
121
144
|
/** TCP services bypass Caddy — no Caddy block. */
|
|
122
145
|
get caddyBlock() { return null }
|
|
123
146
|
|
|
124
|
-
/** Each port needs an explicit security group ingress rule. */
|
|
147
|
+
/** Each port needs an explicit security group ingress rule matching its protocol. */
|
|
125
148
|
get securityGroupPorts() {
|
|
126
|
-
return this.
|
|
127
|
-
if (this.protocol === 'both') return [{ port, protocol: 'tcp' }, { port, protocol: 'udp' }]
|
|
128
|
-
return [{ port, protocol: this.protocol }]
|
|
129
|
-
})
|
|
149
|
+
return this.portEntries.flatMap(expandSecurityGroupRules)
|
|
130
150
|
}
|
|
131
151
|
|
|
132
152
|
get unitName() { return `${this.name}.service` }
|
|
@@ -158,5 +178,6 @@ const fromConfig = (services = []) => {
|
|
|
158
178
|
module.exports = {
|
|
159
179
|
HttpContainerService,
|
|
160
180
|
TcpContainerService,
|
|
181
|
+
normalizePortEntries,
|
|
161
182
|
fromConfig
|
|
162
183
|
}
|