Deploying a Kotlin app to Railway (a Slack bot)
We will deploy a “Hello world” Slack bot to Railway, sourced from GitHub (written in Kotlin).
--
Now that Heroku has no free plan anymore, it’s time to find a new home for our experimental JVM apps. Railway does the job.
1. Codebase
- Create a new Kotlin project.
- If you haven’t yet made
git init
, you should do it now. - Make sure you have a
.gitignore
file at the root with:
/.gradle
/.idea
/build
4. We will use GitHub as the source of the app codebase; Railway will access it and deploy the app from there. Create a new GitHub repository (can be private or public) naming it slack-hello-bot
or similar.
5. Commit and push to your new repository:
git remote add origin GITHUB_REPOSITORY_LINK
git push -u origin main
2. Railway project
We need to set up a Railway project which will serve our Kotlin app created before.
- Go to Railway ▶ register/login ▶ click “New Project” ▶ “Deploy from GitHub repo” ▶ provide access to GitHub ▶ pick the created project (
slack-hello-bot
). - On the Kotlin app’s root folder, create a file named
Procfile
with the following content:web: java -jar build/libs/PROJ_ID-1.0-SNAPSHOT-all.jar
(to get thePROJ_ID
, checksettings.gradle.kts
).
This represents the command that Railway runs to launch the web app. - Railway requires a
stage
target.
At the end ofbuild.gradle.kts
, add:
task("stage") {
dependsOn("shadowJar")
}
3. Slack Bolt app
- Add the following dependencies to
build.gradle.kts
:
dependencies {
implementation("org.slf4j:slf4j-simple:1.+")
implementation("com.slack.api:bolt:1.+")
implementation("com.slack.api:bolt-servlet:1.+")
implementation("com.slack.api:bolt-jetty:1.+")
}
2. Add Gradle Shadow build.gradle.kts
. This will enable the creation of a single fat jar that can be run later in Railway.
plugins {
id("com.github.johnrengelman.shadow") version "7.+"
application
}
// at the bottom:
application {
mainClass.set("SlackMainKt")
}
📝 You may need to click the buttons to refresh Gradle, in the top-right corner of the file in the IDE.
3. At src/main/kotlin/SlackMain.kt
, put:
fun main() {
val app = App()
app.command("/hello") { _, _ ->
Response.ok("world")
}
SlackAppServer(app, getenv("PORT")?.toInt() ?: 8080)
.start()
}
📝 PORT
is an environment variable provided by Railway. It represents the port that Railway exposes. Therefore, we need to serve our app from that port.
4. Commit and push all the local Git changes. The push will automatically trigger a Railway deployment. You can check the deploy status and logs on Railway dashboard.
4. Slack app configuration
Based on the official docs: Building an app with Bolt for Java and Getting Started with Bolt.
- Go to Slack Apps ▶ click “Create New App”.
- Pick “From scratch” ▶ click “Next” ▶ name the app ▶ assign it to a workspace.
- On the left-side menu, go to “OAuth & Permissions” ▶ scroll to “Scopes” ▶ add
chat:write
. - On the menu, click “Slash Commands” ▶ “Create New Command”.
- Fill in the details with:
Command:hello
Request URL:BASE_APP_URL/slack/events
To getBASE_APP_URL
, go to Railway dashboard ▶ pick the app ▶ “web” ▶ “Settings” ▶ “Domains”.
Short Description:hello world
Save the changes. - We need to copy the Slack environment variables from Slack UI to Railway:
Go to “Basic Information” ▶ “App Credentials” ▶ “Signing Secret” ▶ click “Show” ▶ copy it. Go to Railway dashboard ▶ pick the created app ▶ “web” ▶ “Variables” ▶ “New Variable” namedSLACK_SIGNING_SECRET
with the copied value from before. - Going back to the Slack UI ▶ go to “OAuth & Permissions” ▶ click the button “Install to Workspace” ▶ copy the value at “Bot User OAuth Token”. Go back to the Railway ▶ create another env var named
SLACK_BOT_TOKEN
▶ paste the copied value. - Time to test the app! Go to Slack ▶ type
/hello
in any channel ▶ press Enter. You should getworld
as reply.