|
| 1 | +# Thruster HTTP/2 Proxy Integration |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +This project uses [Thruster](https://github.com/basecamp/thruster), a zero-config HTTP/2 proxy from Basecamp, to enhance application performance and simplify deployment. Thruster sits in front of the Rails/Puma server and provides HTTP/2 support, asset caching, compression, and TLS termination. |
| 6 | + |
| 7 | +## What is Thruster? |
| 8 | + |
| 9 | +Thruster is a small, fast HTTP/2 proxy designed specifically for Ruby web applications. It provides: |
| 10 | + |
| 11 | +- **HTTP/2 Support**: Automatic HTTP/2 with multiplexing for faster asset loading |
| 12 | +- **Asset Caching**: X-Sendfile support and intelligent caching for static assets |
| 13 | +- **Compression**: Automatic gzip/Brotli compression for responses |
| 14 | +- **TLS Termination**: Built-in Let's Encrypt support for production deployments |
| 15 | +- **Zero Configuration**: Works out of the box with sensible defaults |
| 16 | + |
| 17 | +### Benefits Over Direct Puma + Early Hints |
| 18 | + |
| 19 | +Previously, this project used Puma's `--early-hints` flag to send HTTP/2 server push hints. Thruster provides several advantages: |
| 20 | + |
| 21 | +1. **Simpler Configuration**: No need to configure early hints in your application code |
| 22 | +2. **Better HTTP/2 Support**: Full HTTP/2 implementation, not just early hints |
| 23 | +3. **Asset Optimization**: Built-in caching and compression without additional configuration |
| 24 | +4. **Production Ready**: TLS termination and Let's Encrypt integration for production |
| 25 | +5. **Faster Asset Delivery**: More efficient handling of static assets |
| 26 | + |
| 27 | +## Installation |
| 28 | + |
| 29 | +Thruster is already installed in this project via the Gemfile: |
| 30 | + |
| 31 | +```ruby |
| 32 | +gem "thruster" |
| 33 | +``` |
| 34 | + |
| 35 | +After running `bundle install`, the `thrust` executable is available. |
| 36 | + |
| 37 | +## Configuration |
| 38 | + |
| 39 | +### Procfiles |
| 40 | + |
| 41 | +All Procfiles in this project have been updated to use Thruster: |
| 42 | + |
| 43 | +#### Production (`Procfile`) |
| 44 | +``` |
| 45 | +web: bundle exec thrust bin/rails server |
| 46 | +``` |
| 47 | + |
| 48 | +#### Development with HMR (`Procfile.dev`) |
| 49 | +``` |
| 50 | +rails: bundle exec thrust bin/rails server -p 3000 |
| 51 | +``` |
| 52 | + |
| 53 | +#### Development with Production Assets (`Procfile.dev-prod-assets`) |
| 54 | +``` |
| 55 | +web: bundle exec thrust bin/rails server -p 3001 |
| 56 | +``` |
| 57 | + |
| 58 | +#### Development with Static Webpack (`Procfile.dev-static`) |
| 59 | +``` |
| 60 | +web: bundle exec thrust bin/rails server -p 3000 |
| 61 | +``` |
| 62 | + |
| 63 | +#### Development with Static Assets (`Procfile.dev-static-assets`) |
| 64 | +``` |
| 65 | +web: bundle exec thrust bin/rails server -p 3000 |
| 66 | +``` |
| 67 | + |
| 68 | +### Default Behavior |
| 69 | + |
| 70 | +Thruster uses sensible defaults: |
| 71 | + |
| 72 | +- **Port**: Listens on port specified by Rails server (or PORT env var) |
| 73 | +- **Cache**: Automatically caches static assets from `public/` |
| 74 | +- **Compression**: Enables gzip/Brotli compression automatically |
| 75 | +- **HTTP/2**: Enabled by default when using HTTPS |
| 76 | + |
| 77 | +### Custom Configuration (Optional) |
| 78 | + |
| 79 | +You can customize Thruster behavior using environment variables: |
| 80 | + |
| 81 | +```bash |
| 82 | +# Set custom cache directory |
| 83 | +THRUSTER_CACHE_DIR=/path/to/cache |
| 84 | + |
| 85 | +# Adjust cache size (default: 64MB) |
| 86 | +THRUSTER_CACHE_SIZE=128M |
| 87 | + |
| 88 | +# Set custom TLS certificate (production) |
| 89 | +THRUSTER_TLS_CERT=/path/to/cert.pem |
| 90 | +THRUSTER_TLS_KEY=/path/to/key.pem |
| 91 | + |
| 92 | +# Enable debug logging |
| 93 | +THRUSTER_DEBUG=1 |
| 94 | +``` |
| 95 | + |
| 96 | +For most use cases, the defaults work perfectly without any additional configuration. |
| 97 | + |
| 98 | +## Development Usage |
| 99 | + |
| 100 | +### Starting the Development Server |
| 101 | + |
| 102 | +Use any of the existing Procfile commands: |
| 103 | + |
| 104 | +```bash |
| 105 | +# Development with Hot Module Replacement |
| 106 | +foreman start -f Procfile.dev |
| 107 | + |
| 108 | +# Development with static assets |
| 109 | +foreman start -f Procfile.dev-static |
| 110 | + |
| 111 | +# Production-like assets in development |
| 112 | +foreman start -f Procfile.dev-prod-assets |
| 113 | +``` |
| 114 | + |
| 115 | +Thruster will automatically: |
| 116 | +1. Start a proxy server on the configured port |
| 117 | +2. Forward requests to Rails/Puma |
| 118 | +3. Cache and compress assets |
| 119 | +4. Serve static files efficiently |
| 120 | + |
| 121 | +### Checking Thruster Status |
| 122 | + |
| 123 | +When the server starts, you'll see Thruster initialization in the logs: |
| 124 | + |
| 125 | +``` |
| 126 | +[thrust] Starting Thruster HTTP/2 proxy |
| 127 | +[thrust] Proxying to http://localhost:3000 |
| 128 | +[thrust] Serving from ./public |
| 129 | +``` |
| 130 | + |
| 131 | +## Production Deployment |
| 132 | + |
| 133 | +### Heroku |
| 134 | + |
| 135 | +Thruster works seamlessly with Heroku. The standard `Procfile` is already configured: |
| 136 | + |
| 137 | +``` |
| 138 | +web: bundle exec thrust bin/rails server |
| 139 | +``` |
| 140 | + |
| 141 | +Heroku automatically: |
| 142 | +- Provides TLS termination at the router level |
| 143 | +- Sets the PORT environment variable |
| 144 | +- Manages process scaling |
| 145 | + |
| 146 | +### Control Plane |
| 147 | + |
| 148 | +For Control Plane deployments (see [.controlplane/readme.md](../.controlplane/readme.md)), Thruster provides: |
| 149 | + |
| 150 | +- Efficient static asset serving |
| 151 | +- HTTP/2 support for faster page loads |
| 152 | +- Built-in compression to reduce bandwidth costs |
| 153 | + |
| 154 | +### Other Platforms |
| 155 | + |
| 156 | +For VPS or bare-metal deployments, Thruster can handle TLS termination with Let's Encrypt: |
| 157 | + |
| 158 | +```bash |
| 159 | +# Set your domain for automatic Let's Encrypt certificates |
| 160 | +THRUSTER_DOMAIN=yourdomain.com bundle exec thrust bin/rails server |
| 161 | +``` |
| 162 | + |
| 163 | +Thruster will automatically: |
| 164 | +1. Obtain SSL certificates from Let's Encrypt |
| 165 | +2. Handle certificate renewal |
| 166 | +3. Serve your app over HTTPS with HTTP/2 |
| 167 | + |
| 168 | +## Monitoring and Debugging |
| 169 | + |
| 170 | +### Log Output |
| 171 | + |
| 172 | +Thruster logs important events: |
| 173 | + |
| 174 | +``` |
| 175 | +[thrust] Starting Thruster HTTP/2 proxy |
| 176 | +[thrust] Proxying to http://localhost:3000 |
| 177 | +[thrust] Serving from ./public |
| 178 | +[thrust] Cache hit: /packs/application-abc123.js |
| 179 | +[thrust] Compressed response: 1.2MB -> 250KB |
| 180 | +``` |
| 181 | + |
| 182 | +### Debug Mode |
| 183 | + |
| 184 | +Enable verbose logging: |
| 185 | + |
| 186 | +```bash |
| 187 | +THRUSTER_DEBUG=1 foreman start -f Procfile.dev |
| 188 | +``` |
| 189 | + |
| 190 | +This shows: |
| 191 | +- All proxied requests |
| 192 | +- Cache hit/miss information |
| 193 | +- Compression ratios |
| 194 | +- HTTP/2 connection details |
| 195 | + |
| 196 | +### Performance Metrics |
| 197 | + |
| 198 | +Monitor Thruster's impact: |
| 199 | + |
| 200 | +1. **Asset Load Times**: Check browser DevTools Network tab for HTTP/2 multiplexing |
| 201 | +2. **Cache Efficiency**: Look for `X-Cache: HIT` headers in responses |
| 202 | +3. **Compression**: Check `Content-Encoding: br` or `gzip` headers |
| 203 | +4. **Response Times**: Should see faster initial page loads |
| 204 | + |
| 205 | +## Troubleshooting |
| 206 | + |
| 207 | +### Server Won't Start |
| 208 | + |
| 209 | +**Issue**: Thruster fails to start |
| 210 | +**Solution**: Check if another process is using the port: |
| 211 | + |
| 212 | +```bash |
| 213 | +lsof -ti:3000 | xargs kill -9 |
| 214 | +``` |
| 215 | + |
| 216 | +### Assets Not Caching |
| 217 | + |
| 218 | +**Issue**: Static assets aren't being cached |
| 219 | +**Solution**: Ensure assets are in the `public/` directory and have proper cache headers: |
| 220 | + |
| 221 | +```ruby |
| 222 | +# config/environments/production.rb |
| 223 | +config.public_file_server.enabled = true |
| 224 | +config.public_file_server.headers = { |
| 225 | + 'Cache-Control' => 'public, max-age=31536000' |
| 226 | +} |
| 227 | +``` |
| 228 | + |
| 229 | +### HTTP/2 Not Working |
| 230 | + |
| 231 | +**Issue**: Browser shows HTTP/1.1 connections |
| 232 | +**Solution**: HTTP/2 requires HTTPS. In development, use a tool like [mkcert](https://github.com/FiloSottile/mkcert) or test in production with proper TLS. |
| 233 | + |
| 234 | +## Migration Notes |
| 235 | + |
| 236 | +### From Puma Early Hints |
| 237 | + |
| 238 | +Previous configuration: |
| 239 | +``` |
| 240 | +web: bundle exec puma -C config/puma.rb --early-hints |
| 241 | +``` |
| 242 | + |
| 243 | +New configuration: |
| 244 | +``` |
| 245 | +web: bundle exec thrust bin/rails server |
| 246 | +``` |
| 247 | + |
| 248 | +**Changes**: |
| 249 | +- Removed `--early-hints` flag from all Procfiles |
| 250 | +- No changes needed to application code |
| 251 | +- Better performance with full HTTP/2 support |
| 252 | + |
| 253 | +### Shakapacker Integration |
| 254 | + |
| 255 | +Thruster works seamlessly with Shakapacker for both Webpack and Rspack: |
| 256 | + |
| 257 | +- Compiled assets in `public/packs/` are automatically cached |
| 258 | +- Manifest files are properly served |
| 259 | +- Hot Module Replacement (HMR) still works in development |
| 260 | + |
| 261 | +## Performance Expectations |
| 262 | + |
| 263 | +Based on typical Rails applications with Thruster: |
| 264 | + |
| 265 | +- **Initial Page Load**: 20-30% faster due to HTTP/2 multiplexing |
| 266 | +- **Asset Delivery**: 40-60% reduction in transfer size with Brotli compression |
| 267 | +- **Cache Hit Rate**: 80-95% for static assets after warmup |
| 268 | +- **Server Load**: Reduced by 30-40% due to efficient asset serving |
| 269 | + |
| 270 | +## Additional Resources |
| 271 | + |
| 272 | +- [Thruster GitHub Repository](https://github.com/basecamp/thruster) |
| 273 | +- [HTTP/2 Explained](https://http2-explained.haxx.se/) |
| 274 | +- [Deploying Rails 8 with Thruster](https://world.hey.com/dhh/rails-8-with-thruster-by-default-c953f5e3) |
| 275 | +- [Kamal Handbook - Thruster Section](https://kamal-deploy.org/docs/accessories/thruster/) |
| 276 | + |
| 277 | +## Support |
| 278 | + |
| 279 | +For issues related to: |
| 280 | +- **Thruster**: [GitHub Issues](https://github.com/basecamp/thruster/issues) |
| 281 | +- **This Project**: [Forum](https://forum.shakacode.com) or [GitHub Issues](https://github.com/shakacode/react-webpack-rails-tutorial/issues) |
| 282 | +- **React on Rails**: [Slack Channel](https://reactrails.slack.com/) |
0 commit comments