Skip Navigation
Show nav
Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
    • .NET
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up
View categories

Categories

  • Heroku Architecture
    • Compute (Dynos)
      • Dyno Management
      • Dyno Concepts
      • Dyno Behavior
      • Dyno Reference
      • Dyno Troubleshooting
    • Stacks (operating system images)
    • Networking & DNS
    • Platform Policies
    • Platform Principles
  • Developer Tools
    • Command Line
    • Heroku VS Code Extension
  • Deployment
    • Deploying with Git
    • Deploying with Docker
    • Deployment Integrations
  • Continuous Delivery & Integration (Heroku Flow)
    • Continuous Integration
  • Language Support
    • Node.js
      • Working with Node.js
      • Node.js Behavior in Heroku
      • Troubleshooting Node.js Apps
    • Ruby
      • Rails Support
      • Working with Bundler
      • Working with Ruby
      • Ruby Behavior in Heroku
      • Troubleshooting Ruby Apps
    • Python
      • Working with Python
      • Background Jobs in Python
      • Python Behavior in Heroku
      • Working with Django
    • Java
      • Java Behavior in Heroku
      • Working with Java
      • Working with Maven
      • Working with Spring Boot
      • Troubleshooting Java Apps
    • PHP
      • PHP Behavior in Heroku
      • Working with PHP
    • Go
      • Go Dependency Management
    • Scala
    • Clojure
    • .NET
      • Working with .NET
  • Databases & Data Management
    • Heroku Postgres
      • Postgres Basics
      • Postgres Getting Started
      • Postgres Performance
      • Postgres Data Transfer & Preservation
      • Postgres Availability
      • Postgres Special Topics
      • Migrating to Heroku Postgres
    • Heroku Key-Value Store
    • Apache Kafka on Heroku
    • Other Data Stores
  • AI
    • Working with AI
    • Heroku Inference
      • Inference API
      • Quick Start Guides
      • AI Models
      • Inference Essentials
    • Vector Database
    • Model Context Protocol
  • Monitoring & Metrics
    • Logging
  • App Performance
  • Add-ons
    • All Add-ons
  • Collaboration
  • Security
    • App Security
    • Identities & Authentication
      • Single Sign-on (SSO)
    • Private Spaces
      • Infrastructure Networking
    • Compliance
  • Heroku Enterprise
    • Enterprise Accounts
    • Enterprise Teams
    • Heroku Connect (Salesforce sync)
      • Heroku Connect Administration
      • Heroku Connect Reference
      • Heroku Connect Troubleshooting
  • Patterns & Best Practices
  • Extending Heroku
    • Platform API
    • App Webhooks
    • Heroku Labs
    • Building Add-ons
      • Add-on Development Tasks
      • Add-on APIs
      • Add-on Guidelines & Requirements
    • Building CLI Plugins
    • Developing Buildpacks
    • Dev Center
  • Accounts & Billing
  • Troubleshooting & Support
  • Integrating with Salesforce
  • Developer Tools
  • Command Line
  • Heroku Exec (SSH Tunneling)

Heroku Exec (SSH Tunneling)

English — 日本語に切り替える

Last updated December 09, 2024

Table of Contents

  • Getting Started
  • Port Forwarding
  • SOCKS Proxy
  • Using Java Debugging Tools
  • Remote Debugging
  • Copying Files From a Dyno
  • Using with Docker
  • Disabling the Feature
  • Limitations

Heroku Exec is a feature for creating secure TCP and SSH tunnels into a dyno. It supports SSH sessions, port forwarding, remote debugging, and inspection with popular Java diagnostic tools.

Heroku Exec is unavailable for Fir-generation apps. Use heroku run:inside instead. See Heroku Generations for more Fir info.

Getting Started

You can use Heroku Exec by running:

$ heroku ps:exec

If you use Exec with a Private Spaces app, a custom buildpack is automatically added to your app, and you must redeploy. A redeploy is not required for apps in the Common Runtime.

$ git commit -m "Heroku Exec" --allow-empty
$ git push heroku main

After deploying your app, run the command again to connect to your web dyno.

$ heroku ps:exec
Establishing credentials... done
Connecting to web.1 on ⬢ your-app...
~ $

By default, Heroku Exec connects to your web.1 dyno, but you can optionally specify a dyno.

$ heroku ps:exec --dyno=web.2
Establishing credentials... done
Connecting to web.2 on ⬢ your-app...
~ $

If you run into problems connecting to a dyno, use the --status flag to check the status of the Exec connection.

$ heroku ps:exec --status
=== limitless-savannah-19617 Heroku Exec status
Dyno   Proxy Status  Dyno Status
─────  ────────────  ───────────
web.1  running       up
web.2  running       up

Port Forwarding

In addition to creating an interactive terminal session, the CLI can forward traffic on a local port to a port inside a dyno. In this example, 9090 is the local port and the dyno port.

$ heroku ps:forward 9090
Listening on 9090 and forwarding to web.1:9090...

Then connect your remote debugger, profiler, or even a browser to localhost:9090 to route your requests through a secure socket to port 9090 in the dyno. To stop port forwarding, use CTRL+C.

SOCKS Proxy

You can also use a local SOCKS proxy to forward traffic on multiple ports. Start the proxy by running this command.

$ heroku ps:socks

With the proxy running, you can access any port inside the dyno. For example:

$ curl --socks5 localhost:1080 0.0.0.0:12345

Using Java Debugging Tools

To use Java debugging tools, you must first install the Heroku CLI Java plugin by running this command.

$ heroku plugins:install @heroku-cli/plugin-java

Then you can open a JConsole connection to a dyno by running this command locally.

$ heroku java:jconsole

The JConsole connection routes through a secure SOCKS proxy created with SSH, which ensures that all traffic is encrypted. But JConsole warns you that the connection is insecure because the JVM isn’t aware of the lower-level encryption.

Run heroku help java for a list of more Java-related commands, such as:

  • heroku java:visualvm
  • heroku java:jmap
  • heroku java:jstack

When Heroku Exec is enabled, the default JAVA_TOOL_OPTIONS environment variable changes to include options that enable JMX for all Java processes in your dyno. You can prevent this action by running:

$ heroku config:set HEROKU_DISABLE_JMX=1

This command disables commands like heroku java:visualvm, which require JMX. But other commands such as ps:exec and java:jmap continue to work. If you want to selectively enable JMX, you can add the $HEROKU_JMX_OPTIONS environment variable to the java command used to run your app.

Remote Debugging

Many popular IDEs provide remote debugging capabilities through an SSH tunnel.

In all cases, you must first configure your application to enable remote debugging. For Node.js, you must add the --inspect=9090 to the node command that starts your app. For example, your Procfile can look like:

web: node --inspect=9090 index.js

For Java applications, you must provide the -agentlib option to configure the Java Debug Wire Protocol (JDWP). For example:

web: java -agentlib:jdwp=transport=dt_socket,server=y,address=9090,suspend=n -jar target/myapp.jar

In both cases, the port 9090 is arbitrary.

After you change your Procfile and redeploy your app, you can start port forwarding with the Heroku Exec client.

$ heroku ps:forward 9090

Finally, connect your IDE or remote debugger to localhost:9090.

For more information on specific vendors, see the IDE documentation.

  • Eclipse
  • IntelliJ IDEA
  • WebStorm

For most JetBrains products, including IntelliJ IDEA and WebStorm, select Edit Configurations and create a new Remote run configuration. Select port 9090 and localhost. Then start the configuration, set a break-point, and open your application.

Copying Files From a Dyno

To copy files from a dyno, run this command on your local machine, not on the dyno.

$ heroku ps:copy filename

This command copies the file in the dyno with the given name to a local file with the same name. You can use the -o option to specify the name of the local file. This command isn’t available to one-off dynos and processes started with heroku run.

Using with Docker

If you’re packaging your app with Docker and deploying via Container Registry, using Heroku Exec isn’t officially supported and requires a few additional setup steps.

Ensure that your Docker image has bash, curl, openssh (tested with 7.2, 7.6, 8.x), ip (found in the iproute2 package in Ubuntu-derived images), and either jq or python installed.

Create a heroku-exec.sh file with this code, and include it in the /app/.profile.d directory of your image.

[ -z "$SSH_CLIENT" ] && source <(curl --fail --retry 3 -sSL "$HEROKU_EXEC_URL")

The heroku-exec.sh file must live in /app/.profile.d, even though your WORKDIR can be different. Here’s an example of a Dockerfile command that adds the file to the correct directory.

ADD ./.profile.d /app/.profile.d

Finally, ensure that the default shell is bash by including this line in your Dockerfile.

RUN rm /bin/sh && ln -s /bin/bash /bin/sh

If you use Docker in a private space, you must add the heroku-exec.sh script to your CMD entry, as .profile.d scripts aren’t run. For example:

CMD bash heroku-exec.sh && node index.js

Disabling the Feature

To disable the feature, run this command.

$ heroku features:disable runtime-heroku-exec

Then optionally remove the Heroku Exec buildpack from your app (Private Spaces only) by running this command.

$ heroku buildpacks:remove heroku/exec

Limitations

Connection

Each Heroku Exec connection lasts a maximum of 1 hour. After an hour, sometimes you must reconnect. Additionally, Heroku Exec isn’t supported in Shield Private Spaces.

Heroku Exec isn’t enabled for one-off or release phase dynos.

Environment Variables

The SSH session created by Heroku Exec doesn’t have the config vars set as environment variables (i.e., env in a session doesn’t list config vars set by heroku config:set).

Shield Private Spaces Compatibility

Due to the high-compliance requirements of apps running in Shield Private Spaces, Heroku Exec isn’t supported.

Keep reading

  • Command Line

Feedback

Log in to submit feedback.

Using CLI Plugins Managing SSH Keys

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure
  • .NET

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing
  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Github
  • LinkedIn
  • © 2025 Salesforce, Inc. All rights reserved. Various trademarks held by their respective owners. Salesforce Tower, 415 Mission Street, 3rd Floor, San Francisco, CA 94105, United States
  • heroku.com
  • Legal
  • Terms of Service
  • Privacy Information
  • Responsible Disclosure
  • Trust
  • Contact
  • Cookie Preferences
  • Your Privacy Choices