1. The problem I’m having:
I am working on my AWS EC2 server and I can’t find the .pem
certificate and key files that Caddy uses to create an TLS connection.
I want to set up a WebSocket server on the same EC2 instance using Caddy.
I am using uWebSockets to enable TLS on the uWebSocket server, uWebSockets’ config needs the .pem
file for both the TLS certificate and key.
For example, here is my SSLConfig
:
// Read SSL/TLS certificate and private key
export const SSL_OPTIONS = {
key_file_name: 'misc/local-key.pem',
cert_file_name: 'misc/local-cert.pem',
passphrase: '1234' // Optional: Remove if no passphrase is set
}
And here is my uWebSockets server file:
/* src/server.ts */
// Externals
import uWS, {
App,
WebSocket,
WebSocketBehavior
} from 'uWebSockets.js'
// Locals
import {
PORT,
SSL_OPTIONS,
IDLE_TIMEOUT,
MAX_LIFETIME,
MAX_BACKPRESSURE,
MAX_PAYLOAD_LENGTH,
} from './utils'
const wsBehavior: WebSocketBehavior<any> = {
// What permessage- deflate compression to use `uWS.DISABLED`,
// `uWS.SHARED_COMPRESSOR` or any of the `uWS.DEDICATED_COMPRESSOR_xxxKB`.
// Defaults to `uWS.DISABLED`.
compression: uWS.SHARED_COMPRESSOR,
// Maximum number of minutes a WebSocket may be connected before being closed
// by the server. 0 disables the feature.
maxLifetime: MAX_LIFETIME,
// Maximum length of allowed backpressure per socket when publishing or
// sending messages. Slow receivers with too high backpressure will be skipped
// until they catch up or timeout. Defaults to 64 * 1024
maxBackpressure: MAX_BACKPRESSURE,
// Maximum length of incoming message
maxPayloadLength: MAX_PAYLOAD_LENGTH,
// Maximum idle time before a connection is closed (in seconds). Disable by
// using 0. Defaults to 120.
idleTimeout: IDLE_TIMEOUT,
// Method called on each new WebSocket connection
open: (ws) => {
console.log('A WebSocket connected')
ws.subscribe('broadcast')
},
// Method called whenever a message is received
message: async (ws, message: ArrayBuffer, isBinary: boolean) => {
const msg = Buffer.from(message).toString('utf8')
console.log(`Received message: ${msg}`)
// Send the message to your Next.js API route
try {
const apiEndpoint = 'https://localhost:3000/api/v1/social-rating/game/wss/local/players'
const response = await fetch(apiEndpoint, {
method: 'POST',
body: msg
})
const json = await response.json()
// Log the response from the Next.js API route
console.log(`API Response: ${response}`)
if (response.status === 200) {
console.log(`API Response: ${response}`)
ws.publish('broadcast', msg, isBinary)
}
} catch (error: any) {
const errorMessage = 'Failed to send message to API route: '
console.error(errorMessage, error)
}
},
// Method called when a connection is closed
close: (ws, code: number, message: ArrayBuffer) => {
const msg = Buffer.from(message).toString()
console.log(`WebSocket closed with code: ${code}, message: ${ msg }`)
}
}
// Main app
const app = uWS./*SSL*/App(SSL_OPTIONS)
.ws('/*', wsBehavior)
.get('/*', (res, req) => {
res.writeStatus('200 OK').end('WebSocket server is running')
})
.listen(PORT, (token: any) => {
if (token) {
console.log(`Server is listening on port ${PORT}`)
} else {
console.log('Failed to listen to port')
}
})
2. Error messages and/or full log output:
Upon reviewing the Caddy logs for tls
, I see:
tls cleaning storage unit {"storage": "FileStorage:/root/.local/share/caddy"}
Here’s a screenshot of the log for clarity:
I tried to access that file path but the EC2 instance won’t let me.
3. Caddy version:
v2.8.4 h1:q3pe0wpBj1OcHFZ3n/1nl4V4bxBrYoSoab7rL9BMYNk=
4. How I installed and ran Caddy:
- Installed by running:
caddy upgrade
- Ran
caddy
by runningsudo caddy run --config /etc/caddy/Caddyfile
a. System environment:
- OS:
Amazon Linux 2023
- AMI ID:
ami-00beae93a2d981137
- Size:
t2.micro
- Docker version:
Docker version 25.0.5, build 5dc9bcc
b. Command:
-
To search for directories with the
caddy
keyword, I ran:sudo find / -type d -name "caddy"
-
To start the Caddy server, I ran the usual:
sudo caddy run --config /etc/caddy/Caddyfile
c. Service/unit/compose file:
d. My complete Caddy config:
canpersonalitychange.com {
encode gzip
header {
Strict-Transport-Security "max-age=31536000;"
Access-Control-Allow-Origin "*"
}
reverse_proxy localhost:3000
}