How to Run a Rails Application on GitHub Codespaces
In this article, I’ll guide you through my experience running a Rails application on GitHub Codespaces. Although there are still a few hurdles to overcome, I hope that by sharing the issues I encountered and how I addressed them, others can have a smoother experience when trying it themselves. Summary First To run a Rails application on GitHub Codespaces, using rails new with the --devcontainer option generally works, but there are a few caveats. General caveats (not specific to Codespaces): Since the access will be through a domain name rather than localhost, you need to adjust config.hosts. Codespaces-specific issues (as of 2025/04/29): POST requests cannot be processed. The application fails the origin check based on the HTTP Origin header, so you need to set config.action_controller.forgery_protection_origin_check to false. Port forwarding in GitHub Codespaces does not work by default. You need to apply one of the following workarounds: Change the port visibility from Private → Public → Private. For some reason, switching back enables Private access (accessible only by yourself). Replace the docker image from the Rails-provided one to a Microsoft-provided image. Disable the forwardPorts setting in .devcontainer/devcontainer.json. What is GitHub Codespaces? GitHub Codespaces is a cloud-based development environment provided by GitHub. https://github.com/features/codespaces It allows you to start developing with just a browser. Note that the browser-based VS Code (github.dev) is mainly a code editor and does not provide a full runtime environment for applications. In contrast, GitHub Codespaces offers not only an editor but also a complete environment where you can run applications. GitHub users are provided with a free monthly allowance of 15 GB storage and 120 core hours. GitHub Pro users receive 20 GB storage and 180 core hours per month. Additionally, a codespace becomes idle after 30 minutes of inactivity and is deleted after 30 days of inactivity. You can change these timeout settings at: https://github.com/settings/codespaces For more details: https://docs.github.com/en/billing/managing-billing-for-your-products/managing-billing-for-github-codespaces Running a Rails Application on GitHub Codespaces The --devcontainer Option The rails new command, which is used to generate a new Rails application, has an option called --devcontainer. When you run rails new with this option, it automatically generates several files under the .devcontainer/ directory. $ rails new sample --devcontainer $ cd sample/ $ ls .devcontainer/ compose.yaml devcontainer.json Dockerfile With these files, you can open the development environment inside a VS Code dev container. Although the detailed explanation of these files is omitted here, you will also use this setup when launching the environment on GitHub Codespaces. Opening the Project in GitHub Codespaces After running rails new, make your first commit and push the code to a GitHub repository. Then, you can access the following URL to open it in GitHub Codespaces: https://codespaces.new/OWNER/REPO You will see a screen confirming that the Codespace is being created. As a side note, you can also add a link directly in your README.md by including the following snippet: [](https://codespaces.new/OWNER/REPO) This will display a badge like the one below: NOTE: Please replace OWNER and REPO with the appropriate values for your repository. Operations on Codespace After launching the Codespace and waiting a short while, you will notice that bin/setup --skip-server is automatically executed in the console. You can find the setting for this behavior in the files generated when you run rails new with the --devcontainer option. .devcontainer/devcontainer.json // Use 'postCreateCommand' to run commands after the container is created. "postCreateCommand": "bin/setup --skip-server" Once setup is complete, you can start the Rails server manually by running: rails s ...However, you still won't be able to access the application just yet. There's a bit more to do! Issue with Port Forwarding Settings on Codespace GitHub Codespaces provides a port forwarding feature that allows external access to a Rails server running inside the Codespace at http://localhost:3000. You can find more information here: https://docs.github.com/en/codespaces/developing-in-a-codespace/forwarding-ports-in-your-codespace By default, ports are set to Private, which means you can access them directly from your browser as long as you are logged in to GitHub with your account. ...However, currently, you need to make some change before you can actually access it — otherwise, access won't work for some reason. Even though the default setting is Private, to make it work whi
In this article, I’ll guide you through my experience running a Rails application on GitHub Codespaces.
Although there are still a few hurdles to overcome, I hope that by sharing the issues I encountered and how I addressed them, others can have a smoother experience when trying it themselves.
Summary First
- To run a Rails application on GitHub Codespaces, using
rails new
with the--devcontainer
option generally works, but there are a few caveats. - General caveats (not specific to Codespaces):
- Since the access will be through a domain name rather than
localhost
, you need to adjustconfig.hosts
.
- Since the access will be through a domain name rather than
- Codespaces-specific issues (as of 2025/04/29):
- POST requests cannot be processed.
- The application fails the origin check based on the HTTP Origin header, so you need to set
config.action_controller.forgery_protection_origin_check
tofalse
.
- The application fails the origin check based on the HTTP Origin header, so you need to set
- Port forwarding in GitHub Codespaces does not work by default.
- You need to apply one of the following workarounds:
- Change the port visibility from Private → Public → Private. For some reason, switching back enables Private access (accessible only by yourself).
- Replace the docker image from the Rails-provided one to a Microsoft-provided image.
- Disable the
forwardPorts
setting in.devcontainer/devcontainer.json
.
- You need to apply one of the following workarounds:
- POST requests cannot be processed.
What is GitHub Codespaces?
GitHub Codespaces is a cloud-based development environment provided by GitHub.
https://github.com/features/codespaces
It allows you to start developing with just a browser.
Note that the browser-based VS Code (github.dev
) is mainly a code editor and does not provide a full runtime environment for applications. In contrast, GitHub Codespaces offers not only an editor but also a complete environment where you can run applications.
GitHub users are provided with a free monthly allowance of 15 GB storage and 120 core hours.
GitHub Pro users receive 20 GB storage and 180 core hours per month.
Additionally, a codespace becomes idle after 30 minutes of inactivity and is deleted after 30 days of inactivity.
You can change these timeout settings at: https://github.com/settings/codespaces
For more details:
https://docs.github.com/en/billing/managing-billing-for-your-products/managing-billing-for-github-codespaces
Running a Rails Application on GitHub Codespaces
The --devcontainer
Option
The rails new
command, which is used to generate a new Rails application, has an option called --devcontainer
.
When you run rails new
with this option, it automatically generates several files under the .devcontainer/
directory.
$ rails new sample --devcontainer
$ cd sample/
$ ls .devcontainer/
compose.yaml devcontainer.json Dockerfile
With these files, you can open the development environment inside a VS Code dev container.
Although the detailed explanation of these files is omitted here, you will also use this setup when launching the environment on GitHub Codespaces.
Opening the Project in GitHub Codespaces
After running rails new
, make your first commit and push the code to a GitHub repository.
Then, you can access the following URL to open it in GitHub Codespaces:
https://codespaces.new/OWNER/REPO
You will see a screen confirming that the Codespace is being created.
As a side note, you can also add a link directly in your README.md
by including the following snippet:
[](https://codespaces.new/OWNER/REPO)
This will display a badge like the one below:
NOTE: Please replace OWNER and REPO with the appropriate values for your repository.
Operations on Codespace
After launching the Codespace and waiting a short while, you will notice that bin/setup --skip-server
is automatically executed in the console.
You can find the setting for this behavior in the files generated when you run rails new
with the --devcontainer
option.
.devcontainer/devcontainer.json
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "bin/setup --skip-server"
Once setup is complete, you can start the Rails server manually by running:
rails s
...However, you still won't be able to access the application just yet. There's a bit more to do!
Issue with Port Forwarding Settings on Codespace
GitHub Codespaces provides a port forwarding feature that allows external access to a Rails server running inside the Codespace at http://localhost:3000
.
You can find more information here:
https://docs.github.com/en/codespaces/developing-in-a-codespace/forwarding-ports-in-your-codespace
By default, ports are set to Private, which means you can access them directly from your browser as long as you are logged in to GitHub with your account.
...However, currently, you need to make some change before you can actually access it — otherwise, access won't work for some reason.
Even though the default setting is Private, to make it work while keeping it Private, you need to manually change it to Public and then back to Private.
NOTE:
I have reported this behavior — where port forwarding does not work unless a manual change is made — in the following discussions:
- https://github.com/orgs/community/discussions/156546
- https://github.com/rails/devcontainer/issues/83
Depending on how this issue is resolved, this workaround may become unnecessary in the future.
Workarounds Other Than Manual Toggling
As mentioned above, by manually changing the port visibility from Private → Public → Private, port forwarding will function properly while maintaining the intended Private setting.
If you don't mind doing this manually, that's fine. However, if you want the port visibility to work correctly immediately after startup, there are a few other methods available.
(That said, from the perspective of "being able to start developing right after running rails new
and opening a Codespace," I personally think these methods are not ideal. I hope this situation will improve in the future.)
Replacing the Docker Image
When you run the rails new --devcontainer
command, it generates a devcontainer configuration with the following content:
.devcontainer/Dockerfile
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version
ARG RUBY_VERSION=3.4.2
FROM ghcr.io/rails/devcontainer/images/ruby:$RUBY_VERSION
By default, the Docker image used is ghcr.io/rails/devcontainer/images/ruby
, maintained by the Rails team.
You can replace this with the Ruby image provided by Microsoft: mcr.microsoft.com/devcontainers/ruby
.
To do so, modify the Dockerfile like this:
.devcontainer/Dockerfile
# Make sure RUBY_VERSION matches the Ruby version in .ruby-version
ARG RUBY_VERSION=3.4.2
+FROM ghcr.io/rails/devcontainer/images/ruby:$RUBY_VERSION
-FROM mcr.microsoft.com/devcontainers/ruby:3.4
With this change, the port forwarding issue is avoided, and you can start development with proper Private port visibility working out of the box.
Remove forwardPorts
When you run rails new
with the --devcontainer
option, the generated .devcontainer/devcontainer.json
file includes the following line:
This setting automatically forwards the specified ports from the container to the host machine.
However, if you disable this and rely on automatic port detection when port 3000 is actually used, you can avoid the issue and start with a properly functioning Private port forwarding setting.
// Use 'forwardPorts' to make a list of ports inside the container available locally.
- "forwardPorts": [3000],
+ // "forwardPorts": [3000],
Solve the "Blocked hosts" Error
At this point, if you try to access the application from your browser, you will encounter an error.
Blocked hosts: symmetrical-spoon-6vxqqgxx4cr6qq-3000.app.github.dev
To allow requests to these hosts, make sure they are valid hostnames (containing only numbers, letters, dashes and dots), then add the following to your environment configuration:
config.hosts << "symmetrical-spoon-6vxqqgxx4cr6qq-3000.app.github.dev"
For more details view: the Host Authorization guide
To resolve this, as indicated in the error message, you need to add the host to config.hosts
.
We will use environment variables set when running in GitHub Codespaces.
config/environments/development.rb
Rails.application.configure do
if ENV["CODESPACES"] == "true"
# Add the Codespace domain to the list of allowed hosts.
# Alternatively, if you prefer simplicity, you could `config.hosts.clear` instead.
#
codespaces_port_forwarding_domain = ENV["GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN"]
codespace_name = ENV["CODESPACE_NAME"]
host = "#{codespace_name}-3000.#{codespaces_port_forwarding_domain}"
config.hosts << host
end
# (Other settings omitted...)
end
After editing config/environments/development.rb
, stop the currently running rails s
server, restart it, and then refresh your browser.
You should now be able to access the application without issues.
POST Requests Cannot Be Handled
Following the steps so far, your Rails application will run in GitHub Codespaces.
However, at this point, only GET requests are handled successfully - POST requests will still fail.
You will encounter this issue when implementing features that use forms, for example.
ActionController::InvalidAuthenticityToken (HTTP Origin header (http://localhost:3000) didn't match request.base_url (https://symmetrical-spoon-6vxqqgxx4cr6qq-3000.app.github.dev)):
This error occurs because the HTTP Origin header does not match the actual request URL.
(ruby) request.base_url
"https://symmetrical-spoon-6vxqqgxx4cr6qq-3000.app.github.dev"
(ruby) request.origin
"http://localhost:3000"
(rdbg)
However, from the browser's perspective, the Origin header is correctly being set based on the currently accessed domain.
It seems that somewhere within the network layer that GitHub Codespaces uses to expose ports externally, the Origin header is being rewritten.
I have reported this issue, so the situation might change in the future. (If it does, I will update this article.)
https://github.com/orgs/community/discussions/156532
Allowing POST Requests to Work in GitHub Codespaces
NOTE:
I have reported the issue regarding the rewriting of the Origin header here:
https://github.com/orgs/community/discussions/156532Depending on how this issue is resolved, the workaround described below might become unnecessary in the future.
The check that causes the error is controlled by the Rails configuration setting config.action_controller.forgery_protection_origin_check
.
3.9.8 config.action_controller.forgery_protection_origin_check (Rails Guides)
Configures whether the HTTP
Origin
header should be checked against the site's origin as an additional CSRF defense.
Ideally, we would like to respect the default value as much as possible.
However, to get Rails applications working in GitHub Codespaces, I adjusted the configuration to disable this setting only when running in Codespaces.
config/environments/development.rb
Rails.application.configure do
if ENV["CODESPACES"]
codespaces_port_forwarding_domain = ENV["GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN"]
codespace_name = ENV["CODESPACE_NAME"]
host = "#{codespace_name}-3000.#{codespaces_port_forwarding_domain}"
config.hosts << host
+
+ warn "Disabling the CSRF protection Origin header check in GitHub Codespaces"
+ config.action_controller.forgery_protection_origin_check = false
end
With this change, POST requests now work as expected!
Summary & Promotion
GitHub Codespaces is a great choice for easily experiencing a sample application development environment directly in your browser.
Of course, you can also use it for actual development.
As explained earlier, several adjustments are needed to run a Rails application smoothly.
Also, you need to be aware of some points regarding port forwarding settings, but there are workable solutions for them.
As a related note, I have created a Ruby gem called active_record_compose,
which provides a way to compose multiple ActiveRecord models and treat them as if they were a single model.
I have prepared a sample application environment to try it out directly on GitHub Codespaces — feel free to check it out!
I also wrote an article about the gem here: