R
Railway•3mo ago
Budi

Private networking in SvelteKit app

I've deployed a SvelteKit application on Railway using a Dockerfile. Within that project I have a separate service for cron jobs, also deployed with a Dockerfile. The cron service calls endpoints on my SvelteKit application. This works fine using the public domain of the app service using HTTPS, but when attempting to use private networking it doesn't work. In my app service, I've configured the server to listen on 0.0.0.0 with Railway's injected port. This builds well and logs Listening on 0.0.0.0:8080, so I know it's working.
vite.config.ts:

import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';

export default defineConfig({
plugins: [sveltekit()],
optimizeDeps: {
include: ['src/lib/components/**/*.svelte', 'src/routes/**/*.svelte']
},

/* Railway requires http:// to be used for private networking, as well as a port to specified. This is injected automatically during run time.

https://docs.railway.app/guides/public-networking#port-variable
https://docs.railway.app/guides/private-networking

*/
server: {
port: Number(process.env.PORT),
host: process.env.HOST || '0.0.0.0'
}
});
vite.config.ts:

import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';

export default defineConfig({
plugins: [sveltekit()],
optimizeDeps: {
include: ['src/lib/components/**/*.svelte', 'src/routes/**/*.svelte']
},

/* Railway requires http:// to be used for private networking, as well as a port to specified. This is injected automatically during run time.

https://docs.railway.app/guides/public-networking#port-variable
https://docs.railway.app/guides/private-networking

*/
server: {
port: Number(process.env.PORT),
host: process.env.HOST || '0.0.0.0'
}
});
26 Replies
Percy
Percy•3mo ago
Project ID: 95e92fe0-66e9-4eed-86df-2cdc05218e79
Budi
BudiOP•3mo ago
95e92fe0-66e9-4eed-86df-2cdc05218e79
Budi
BudiOP•3mo ago
Here's my cron-service.ts, which also deploys with no problems.
cron-service.ts:

...
const CRON_SECRET = process.env.CRON_SECRET;
const NODE_ENV = process.env.NODE_ENV || 'development';
const PORT = process.env.PORT;

/* Railway requires http:// to be used for private networking, as well as a port to specified. This is injected automatically during run time.

https://docs.railway.app/guides/public-networking#port-variable
https://docs.railway.app/guides/private-networking

*/
const ORIGIN =
NODE_ENV === 'production'
? `http://${process.env.MAIN_APP_PRIVATE_DOMAIN}:${PORT}`
: `${process.env.MAIN_APP_DEV_ORIGIN}`;
...
cron-service.ts:

...
const CRON_SECRET = process.env.CRON_SECRET;
const NODE_ENV = process.env.NODE_ENV || 'development';
const PORT = process.env.PORT;

/* Railway requires http:// to be used for private networking, as well as a port to specified. This is injected automatically during run time.

https://docs.railway.app/guides/public-networking#port-variable
https://docs.railway.app/guides/private-networking

*/
const ORIGIN =
NODE_ENV === 'production'
? `http://${process.env.MAIN_APP_PRIVATE_DOMAIN}:${PORT}`
: `${process.env.MAIN_APP_DEV_ORIGIN}`;
...
Unfortunately, my logs show a connection error Error executing test cron job: request to http://sveltecareers.railway.internal:8080/api/cron-tester failed, reason: connect ECONNREFUSED fd12:3663:d458::e6:bba7:55ec:8080. Any idea why this is happening? I believe the ports line up and I'm making a HTTP request. A collorary question is how to access the ${{sveltecareers.PORT}} variable as described in https://docs.railway.app/guides/private-networking#use-internal-hostname-and-port. I cannot access the main app service's PORT variable from the cron-schedule service. I've worked around that by referencing process.env.PORT directly in the cron-service.ts assuming that the injected PORT would be the same, which it appears to be (8080). Thanks! Loving the platform so far.
Railway Docs
Private Networking | Railway Docs
Documentation for Railway
Brody
Brody•3mo ago
the injected port would be the same, but its never good to assume that, you would want to set a PORT service variable on the SvelteKit service so that you can reference it on the cron service. as for the ECONNREFUSED error, remove the server config, and then simply set a HOST service variable to :: since the private network is IPv6 only.
Budi
BudiOP•3mo ago
Thanks for the quick response @Brody! When setting the PORT service variable on the SvelteKit service, is there any way to retrieve this as a Railway provided variable? Or is PORT only made available during runtime, but not in the GUI? I wasn't able to select it from the dropdown in the service variables menu. Do I have to set a fixed port, like 8080 now that I know that's the injected one? I don't understand what you mean with setting a HOST service. Do you mean to remove the server property I had defined from the vite.config.ts altogether?
No description
Brody
Brody•3mo ago
yeah you are right, its only available during runtime, you can just set a fixed port in the UI though.
Budi
BudiOP•3mo ago
Ah sorry I think I'm grokking now. You're suggesting I set a HOST service variable. On the SvelteKit Railway service or the cron service?
Brody
Brody•3mo ago
yes, service variable, on the SvelteKit service and also remove the server property in the config file, its not needed
Budi
BudiOP•3mo ago
OK so summarizing: On the SvelteKit service I remove the service prop from the vite.config.ts. I set a fixed PORT service variable to 8080 instead, and a HOST service variable to ::. This allows me to retrieve these on the cron service, where I define the full private origin as: http://${{sveltecareers.RAILWAY_PRIVATE_DOMAIN}}${{sveltecareers.HOST}}${{sveltecareers.PORT}}. Is that right?
Brody
Brody•3mo ago
you got most correct. the url should be made like this http://${{sveltecareers.RAILWAY_PRIVATE_DOMAIN}}:${{sveltecareers.PORT}} the HOST variable is just set so that the server knows to listen on IPv6 is all
Budi
BudiOP•3mo ago
Ah I see. But I don't need to specify this in vite for the SvelteKit build, because Railway will inject this during run time? Do I not use double colons in the private origin? Just single colon?
Brody
Brody•3mo ago
yeah the SvelteKit server will look for and use a HOST variable
Budi
BudiOP•3mo ago
(First time doing private networking on any hosting service and I'm new to IP standards like IPv6, so bear with me 😅)
Brody
Brody•3mo ago
not sure what you mean, simply set HOST=:: in the SvelteKit service, no need to overthink this right now
Budi
BudiOP•3mo ago
Funny, today I learned that https:// always defaults to port 443. And that explains why I need to define a port when using http://. OK got it, thanks Brody. Will work on implementing this r/n.
Brody
Brody•3mo ago
set HOST=:: and PORT=8080 on sveltecareers set MAIN_APP_PRIVATE_DOMAIN="http://${{sveltecareers.RAILWAY_PRIVATE_DOMAIN}}:${{sveltecareers.PORT}}" on cron-service and then simply use MAIN_APP_PRIVATE_DOMAIN when you call sveltecareers
Budi
BudiOP•3mo ago
🫡 This worked, thanks for helping me fix. It may be worthwhile updating the private networking docs to clarify that while the PORT variable is automatically injected by Railway during runtime, it's not accessible as a reference variable and needs to be set manually. Unrelated question -- the SvelteKit and the cron scheduler are both in a monorepo. I'm deploying based on Github commits. Is there any way to only deploy one service when a particular file or folder in my repo changes? Right now when I change the cron service, the whole base app re-deploys.
Brody
Brody•3mo ago
its not specific to private networking, i think its mentioned elsewhere in the docs though. you want watch paths - https://docs.railway.app/guides/monorepo#watch-paths
Budi
BudiOP•3mo ago
Oooh that's sweet, will try now. Works like a charm, thanks again! Tagging this as solved.
Brody
Brody•3mo ago
no problem!
Budi
BudiOP•3mo ago
After implementing your feedback, this branch passed my CI/CD checks and I merged onto my main branch. I then updated the branch to be watched to main in my services. However since redeploying, they are both showing strange deploy logs. The cron scheduler runs into an import issue:
> sveltecareers-cron-service@1.0.0 start /app

> rm -rf dist && tsc && node dist/cron-service.js



ORIGIN http://sveltecareers.railway.internal:8080

Bree cron scheduler started successfully.

Worker for job "test-logger" online undefined

Worker for job "test-logger" had an error {

err: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/app/dist/utils' imported from /app/dist/jobs/test-logger.js

at finalizeResolution (node:internal/modules/esm/resolve:265:11)

at moduleResolve (node:internal/modules/esm/resolve:933:10)

at defaultResolve (node:internal/modules/esm/resolve:1169:11)

at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:540:12)

at ModuleLoader.resolve (node:internal/modules/esm/loader:509:25)

at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:239:38)

at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:96:40)

at link (node:internal/modules/esm/module_job:95:36) {

code: 'ERR_MODULE_NOT_FOUND',

url: 'file:///app/dist/utils'

}

}
> sveltecareers-cron-service@1.0.0 start /app

> rm -rf dist && tsc && node dist/cron-service.js



ORIGIN http://sveltecareers.railway.internal:8080

Bree cron scheduler started successfully.

Worker for job "test-logger" online undefined

Worker for job "test-logger" had an error {

err: Error [ERR_MODULE_NOT_FOUND]: Cannot find module '/app/dist/utils' imported from /app/dist/jobs/test-logger.js

at finalizeResolution (node:internal/modules/esm/resolve:265:11)

at moduleResolve (node:internal/modules/esm/resolve:933:10)

at defaultResolve (node:internal/modules/esm/resolve:1169:11)

at ModuleLoader.defaultResolve (node:internal/modules/esm/loader:540:12)

at ModuleLoader.resolve (node:internal/modules/esm/loader:509:25)

at ModuleLoader.getModuleJob (node:internal/modules/esm/loader:239:38)

at ModuleWrap.<anonymous> (node:internal/modules/esm/module_job:96:40)

at link (node:internal/modules/esm/module_job:95:36) {

code: 'ERR_MODULE_NOT_FOUND',

url: 'file:///app/dist/utils'

}

}
It pertains to this import, which should work fine. I've confirmed the path holds true for the dist folder which tsconfig.ts is successfully configured to build into. Any idea what could be going wrong? The exact same codebase worked when I had it deployed via Github onto Railway in my previous branch.
No description
Brody
Brody•3mo ago
I'm sorry but we wouldn't be able to provide coding help here perhaps you have the import named wrong or the file named incorrectly, but beyond this we can't help here, these forums are for platform help
Budi
BudiOP•3mo ago
Sure I understand. I'm just trying to ascertain why this deployment would have worked well when on a different branch, but failed now that I merged it. I must have made a mistake somewhere, but struggle to determine what it is.
Brody
Brody•3mo ago
really sorry but we can't offer support for application level issues
Budi
BudiOP•3mo ago
Understood I'll try resolve in the SvelteKit Discord. Thanks for checking.
Brody
Brody•3mo ago
sounds good
Want results from more Discord servers?
Add your server