So I’m documenting here in case anyone else needs this - how to make appsmith go through a forward proxy.
The solution I posted before (above) did not work for api requests, since appsmith uses netty lib that does not support either env vars or -Dhttp_proxy java startup parameters. This means that appsmith will not access api endpoints outside local network when there is a forward proxy to access internet. For example, in this configuration you cannot reach https://www.google.com.
There is a ticket on github to solve this, but it’s not yet closed, so for now I’m using this solution.
We will be installing a transparent proxy and setting iptables rules to route all traffic on ports 80 and 443 to it. This transparent proxy will route the traffic through the forward proxy to the internet. After this setup, everything just works with no need to configure any application or env vars.
The setup is 5 steps long.
1 - docker - start appsmith in host network mode
As I couldn’t find the correct iptables rules that work with the default docker bridged setup, instead I just started appsmith with host network mode, which in fact starts all services in the host network, occupying its ports. This means you’ll have trouble if ports are in use already in the host or other containers in host mode. Appsmith uses ports 80, 443, and 9001, so these must be unused before starting the containers.
To do this, you just have to create a docker-composer.override.yml like this:
services:
appsmith:
network_mode: "host"
That’s it.
2 - configure host network
sysctl -w net.ipv4.ip_forward=1
sysctl -w net.ipv6.conf.all.forwarding=1
sysctl -w net.ipv4.conf.all.send_redirects=0
3 - install a transparent proxy
I used go-any-proxy (GitHub - ryanchapman/go-any-proxy: A transparent tcp proxy (no decryption necessary) (golang). It can forward to upstream proxies (e.g. corporate) and CONNECT on any port through an upstream proxy, giving internet access to external internet resources.) but you can use any you like.
It’s a question of installing golang, and compiling any_proxy binary. You can do this on another container, and just copy out the binary and use anywhere you like.
4 - create user to run proxy, and run it in background
sudo useradd --create-home anyproxy
sudo copy any_proxy /home/anyproxy/any_proxy
sudo chown anyproxy:anyproxy /home/anyproxy/any_proxy
sudo -u anyproxy -H bash -c '/home/anyproxy/any_proxy -l :3129 -d "[10.230.70.1/8](http://10.230.70.1/8)" -p "[192.168.2.1:8080](http://192.168.2.1:8080/)"' &
-d = no proxy destinations if you want
-p = upstream proxy if exists
& = start in background (as daemon/service)
5 - create iptables rules to route traffic to the transparent proxy (any_proxy on port 3129)
sudo iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner anyproxy --dport 80 -j REDIRECT --to-port 3129
sudo iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner anyproxy --dport 443 -j REDIRECT --to-port 3129
sudo ip6tables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner anyproxy --dport 80 -j REDIRECT --to-port 3129
sudo ip6tables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner anyproxy --dport 443 -j REDIRECT --to-port 3129
You can find good instructions and explanation here: Transparent Proxying.
That’s it. You can now test by using curl:
curl -v http://majesticyoungquietspell.neverssl.com/online
curl -v https://catfact.ninja/fact
And you can test the same urls on appsmith by creating simple api requests. Just be sure there are no http_proxy, https_proxy or no_proxy env vars.
I still have to persist this between boots, so I’m planning on running any_proxy as a service that sets the iptable rules on start, adapting this init.d script:
Hope this is useful to someone else.