@ossy/deployment-tools 1.21.3 → 1.21.4
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,14 @@
|
|
|
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.4 (2026-05-26)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @ossy/deployment-tools
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
## 1.21.3 (2026-05-26)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @ossy/deployment-tools
|
package/README.md
CHANGED
|
@@ -75,9 +75,7 @@ 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.
|
|
79
|
-
|
|
80
|
-
Use this for game servers or any other raw socket protocol.
|
|
78
|
+
No Caddy block. Ports are mapped directly (`HOST:CONTAINER`) and opened in the EC2 security group. Use this for game servers or any other raw socket protocol.
|
|
81
79
|
|
|
82
80
|
```json
|
|
83
81
|
"services": [
|
|
@@ -87,15 +85,6 @@ Use this for game servers or any other raw socket protocol.
|
|
|
87
85
|
"image": "itzg/minecraft-server",
|
|
88
86
|
"ports": [25565],
|
|
89
87
|
"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
|
-
]
|
|
99
88
|
}
|
|
100
89
|
]
|
|
101
90
|
```
|
|
@@ -105,8 +94,8 @@ Use this for game servers or any other raw socket protocol.
|
|
|
105
94
|
| `name` | Unique service name — Docker container name and systemd unit. |
|
|
106
95
|
| `type` | Must be `"tcp"` to enable this mode. |
|
|
107
96
|
| `image` | Docker image to pull and run. |
|
|
108
|
-
| `ports` |
|
|
109
|
-
| `protocol` |
|
|
97
|
+
| `ports` | Array of port numbers to expose on the host and open in the security group. |
|
|
98
|
+
| `protocol` | `"tcp"` (default), `"udp"`, or `"both"`. |
|
|
110
99
|
|
|
111
100
|
**Fixed built-in services** (always present, not configurable via `services`):
|
|
112
101
|
- `ossy-api` — the Ossy API (`ghcr.io/ossy-se/api:latest`, port 3001)
|
|
@@ -133,38 +122,6 @@ Each platform is a CDK `Stage` containing five stacks:
|
|
|
133
122
|
|
|
134
123
|
The Elastic IP ensures the EC2 instance can be replaced (instance type changes, user data updates) without breaking DNS or CloudFormation cross-stack exports.
|
|
135
124
|
|
|
136
|
-
## Destroy + redeploy
|
|
137
|
-
|
|
138
|
-
`<platformName>` is the `platformName` field in `packages/infrastructure/platforms.json` (CDK stage id). `<aws-profile>` is your AWS CLI profile for that account. List stacks: `npx cdk list --profile <aws-profile>`.
|
|
139
|
-
|
|
140
|
-
Full platform teardown:
|
|
141
|
-
|
|
142
|
-
```bash
|
|
143
|
-
cd packages/deployment-tools
|
|
144
|
-
npx cdk destroy '<platformName>/**' --profile <aws-profile>
|
|
145
|
-
```
|
|
146
|
-
|
|
147
|
-
Recreate (CDK applies stacks in dependency order):
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
npx cdk deploy '<platformName>/**' --profile <aws-profile>
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
Recycle **only the EC2 host** (keep S3, CDN, and backups):
|
|
154
|
-
|
|
155
|
-
```bash
|
|
156
|
-
npx cdk destroy '<platformName>/dns' --profile <aws-profile>
|
|
157
|
-
npx cdk destroy '<platformName>/deployment-target' --profile <aws-profile>
|
|
158
|
-
npx cdk deploy '<platformName>/deployment-target' --profile <aws-profile>
|
|
159
|
-
npx cdk deploy '<platformName>/dns' --profile <aws-profile>
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
Do not destroy `storage-static` unless you intend to drop media storage (bucket is `RETAIN` and may remain in the account anyway).
|
|
163
|
-
|
|
164
|
-
The S3 bucket and **AWS Backup vault** use `RETAIN` so media and recovery points survive a stack delete. CloudFront and the backup *plan* are removed with the stack.
|
|
165
|
-
|
|
166
|
-
If deploy fails with **BackupVault already exists** after a full destroy, a retained vault is still in the account (`<platformName>-static-media-backup`). Delete it in AWS Backup (empty recovery points first), or import it into the new stack.
|
|
167
|
-
|
|
168
125
|
## Bootstrapping a new platform
|
|
169
126
|
|
|
170
127
|
```bash
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ossy/deployment-tools",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.4",
|
|
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": "296ec9d1c354589c223e533b230535d2b4e6db84"
|
|
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 {
|
|
21
|
-
* @property {'tcp'|'udp'|'both'} [protocol] -
|
|
20
|
+
* @property {number[]} ports - ports to open on the host and in the EC2 security group
|
|
21
|
+
* @property {'tcp'|'udp'|'both'} [protocol] - 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,38 +11,14 @@
|
|
|
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 {
|
|
15
|
-
* @property {'tcp'|'udp'|'both'} [protocol] -
|
|
16
|
-
*
|
|
17
|
-
* @typedef {Object} TcpPortEntry
|
|
18
|
-
* @property {number} port
|
|
19
|
-
* @property {'tcp'|'udp'|'both'} protocol
|
|
14
|
+
* @property {number[]} ports - ports to expose directly (same inside and outside container)
|
|
15
|
+
* @property {'tcp'|'udp'|'both'} [protocol] - defaults to 'tcp'
|
|
20
16
|
*
|
|
21
17
|
* @typedef {HttpServiceConfig|TcpServiceConfig} ContainerServiceConfig
|
|
22
18
|
*/
|
|
23
19
|
|
|
24
20
|
const BASE_HTTP_PORT = 3002 // 3000 = platform runtime, 3001 = API
|
|
25
21
|
|
|
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
|
-
|
|
46
22
|
// ---------------------------------------------------------------------------
|
|
47
23
|
// HTTP service — reverse-proxied through Caddy, container listens on port 3000
|
|
48
24
|
// ---------------------------------------------------------------------------
|
|
@@ -104,23 +80,23 @@ ${this.domain} {
|
|
|
104
80
|
}
|
|
105
81
|
|
|
106
82
|
// ---------------------------------------------------------------------------
|
|
107
|
-
// TCP/UDP service — bypasses Caddy,
|
|
108
|
-
//
|
|
109
|
-
// Security group ingress still comes from securityGroupPorts below.
|
|
83
|
+
// TCP/UDP service — bypasses Caddy, ports exposed directly on the host.
|
|
84
|
+
// Used for game servers and any other raw socket services.
|
|
110
85
|
// ---------------------------------------------------------------------------
|
|
111
86
|
|
|
112
87
|
class TcpContainerService {
|
|
113
88
|
constructor({ name, image, ports, protocol = 'tcp' }) {
|
|
114
89
|
this.name = name
|
|
115
90
|
this.image = image
|
|
116
|
-
this.
|
|
91
|
+
this.ports = ports
|
|
92
|
+
this.protocol = protocol // 'tcp' | 'udp' | 'both'
|
|
117
93
|
}
|
|
118
94
|
|
|
119
95
|
get systemdUnitFile() {
|
|
120
|
-
const
|
|
96
|
+
const portMappings = this.ports.map(p => `-p ${p}:${p}`).join(' \\\n ')
|
|
121
97
|
return `
|
|
122
98
|
[Unit]
|
|
123
|
-
Description=Container service: ${this.name} (
|
|
99
|
+
Description=Container service: ${this.name} (${this.protocol.toUpperCase()} ${this.ports.join(', ')})
|
|
124
100
|
After=network.target docker.service
|
|
125
101
|
Requires=docker.service
|
|
126
102
|
|
|
@@ -129,7 +105,8 @@ EnvironmentFile=/etc/environment
|
|
|
129
105
|
ExecStartPre=-/usr/bin/docker rm -f ${this.name}
|
|
130
106
|
ExecStartPre=/usr/bin/docker pull ${this.image}
|
|
131
107
|
ExecStart=/usr/bin/docker run --name ${this.name} \\
|
|
132
|
-
--network
|
|
108
|
+
--network ossy-network \\
|
|
109
|
+
${portMappings} \\
|
|
133
110
|
--env-file /etc/environment \\
|
|
134
111
|
${this.image}
|
|
135
112
|
ExecStop=/usr/bin/docker stop ${this.name}
|
|
@@ -144,9 +121,12 @@ WantedBy=multi-user.target
|
|
|
144
121
|
/** TCP services bypass Caddy — no Caddy block. */
|
|
145
122
|
get caddyBlock() { return null }
|
|
146
123
|
|
|
147
|
-
/** Each port needs an explicit security group ingress rule
|
|
124
|
+
/** Each port needs an explicit security group ingress rule. */
|
|
148
125
|
get securityGroupPorts() {
|
|
149
|
-
return this.
|
|
126
|
+
return this.ports.flatMap(port => {
|
|
127
|
+
if (this.protocol === 'both') return [{ port, protocol: 'tcp' }, { port, protocol: 'udp' }]
|
|
128
|
+
return [{ port, protocol: this.protocol }]
|
|
129
|
+
})
|
|
150
130
|
}
|
|
151
131
|
|
|
152
132
|
get unitName() { return `${this.name}.service` }
|
|
@@ -178,6 +158,5 @@ const fromConfig = (services = []) => {
|
|
|
178
158
|
module.exports = {
|
|
179
159
|
HttpContainerService,
|
|
180
160
|
TcpContainerService,
|
|
181
|
-
normalizePortEntries,
|
|
182
161
|
fromConfig
|
|
183
162
|
}
|