How do you access the VyOS http api with curl from an external host with VyOS hosted inside a docker container?

My goal here is to create a router that is completely configurable through a curl calls and the python requests library. I am stuck because I cannot get any curl calls to register with the VyOS image inside the container from an external source i.e. another machine on the same network.

I have VyOS from the May 1st 2023 nightly build ISO running successfully inside a docker container on a Ubuntu 20.04. I also successfully configured a macvlan interface from docker network and from the Ubuntu host. I am able to ping the container from the docker host as well as from any arbitrary external computer on the same subnet.

Links I followed:

1. https://docs.vyos.io/en/latest/installation/virtual/docker.html
2. https://vyos.net/get/nightly-builds/
3. https://docs.vyos.io/en/latest/configuration/service/https.html#cfgcmd-set-service-https-api-debug
4. https://docs.vyos.io/en/latest/automation/vyos-api.html

I first created the docker side macvlan:

docker network create -d macvlan --subnet=10.151.192.0/20 --gateway=10.151.192.1 -o parent=enp88s0 macvlan-vyos-driver

I started my container with this:

docker run -d --network=macvlan-vyos-driver --rm --name vyos --privileged -v /lib/modules:/lib/modules -v $(pwd)/config:/config vyos:1.4-rolling-202305010317 /sbin/init

I then entered the container with this:

docker exec -it vyos su vyos

I configured the http to be enabled with this:

configure
set service https api
set service https api debug
set service https api keys id theid key thepass
commit
save
exit

I then checked for port 8080 to be listened to:

ss -lntp

And I can see the port is listening:

$ ss -lntp | grep 8080
LISTEN 0      2048       127.0.0.1:8080       0.0.0.0:*

I can then demonstrate that curling the http server is possible from inside the container:

curl --location --request POST 'http://127.0.0.1:8080/retrieve' --form data='{"op": "showConfig", "path": []}' --form key='thepass'

And the output from inside the container:

curl --location --request POST 'http://127.0.0.1:8080/retrieve' --form data='{"op": "showConfig", "path": []}' --form key='thepass'
{"success": true, "data": {"interfaces": {}, "service": {"https": {"api": {"debug": {}, "keys": {"id": {"theid": {"key": "thepass"}}}}}, "ntp": {"allow-client": {"address": ["0.0.0.0/0", "::/0"]}, "server": {"time1.vyos.net": {}, "time2.vyos.net": {}, "time3.vyos.net": {}}}}, "system": {"config-management": {"commit-revisions": "100"}, "conntrack": {"modules": {"ftp": {}, "h323": {}, "nfs": {}, "pptp": {}, "sip": {}, "sqlnet": {}, "tftp": {}}}, "console": {"device": {"ttyS0": {"speed": "115200"}}}, "host-name": "vyos", "login": {"user": {"vyos": {"authentication": {"encrypted-password": "$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/", "plaintext-password": ""}}}}, "syslog": {"global": {"facility": {"all": {"level": "info"}, "protocols": {"level": "debug"}}}}}}, "error": null}

I know my container is attached to the network because of this output:

docker inspect vyos -f "{{json .NetworkSettings.Networks }}"
{"macvlan-vyos-driver":{"IPAMConfig":null,"Links":null,"Aliases":["cef65ab04a83"],"NetworkID":"f04b77e68d297b450d15fce11622e9cb0878f79af471d6a8ebcf4b1bd9b79664","EndpointID":"697e5fb2387962866a207220598a94666b312cb5429fce74d4708402c4f48ce3","Gateway":"10.151.192.1","IPAddress":"10.151.192.2","IPPrefixLen":20,"IPv6Gateway":"","GlobalIPv6Address":"","GlobalIPv6PrefixLen":0,"MacAddress":"02:42:0a:97:c0:02","DriverOpts":null}}

But, when I try to curl the http server from the docker host, I get this output:

curl --location --request POST 'http://10.151.200.182:8080/retrieve' --form data='{"op": "showConfig", "path": []}' --form key='thepass'
curl: (7) Failed to connect to 10.151.200.182 port 8080: Connection refused

So, my question is:

What am I doing wrong in my VyOS configuration that I cannot access the http api from outside the container?
What should I do to fix my configuration to be able to call curl from outside the docker container?

Note:
I was looking here:

https://forum.vyos.io/t/vyos-as-docker-container-journey/6128

And I wasn’t sure how that setup is different from mine. Any help would be appreciated. Thanks!

Hi,

try to set a allow rule to access the api . I am not sure if you need a extra firewall rule to access the api from outside. I am also struggling with the api…

set service https virtual-host allow-client address

8080 listen on 127.0.0.1, you should request to 443, i.e.

curl --location -k --request POST 'https://10.151.200.182/retrieve' --form data='{"op": "showConfig", "path": []}' --form key='foo'

I am still not able to get a valid curl response from outside the docker container, even when following your modified curl command:

user@device:~$ curl --location -k --request POST 'https://10.151.200.182/retrieve' --form data='{"op": "showConfig", "path": []}' --form key='thepass'
curl: (7) Failed to connect to 10.151.200.182 port 443: Connection refused
user@device:~$

These are the steps I followed, with much more detail.
I can see that port 443 is not exposed from inside the VyOS container when I run ss -lntp.
When I run ss -lntp from the docker host, I can see that the port is available.

user@host:~$ ss -lntp
State                             Recv-Q                            Send-Q                                                       Local Address:Port                                                       Peer Address:Port                           Process
LISTEN                            0                                 4096                                                         127.0.0.53%lo:53                                                              0.0.0.0:*
LISTEN                            0                                 128                                                                0.0.0.0:22                                                              0.0.0.0:*
LISTEN                            0                                 5                                                                127.0.0.1:631                                                             0.0.0.0:*
LISTEN                            0                                 4096                                                               0.0.0.0:443                                                             0.0.0.0:*
LISTEN                            0                                 128                                                                   [::]:22                                                                 [::]:*
LISTEN                            0                                 5                                                                    [::1]:631                                                                [::]:*
LISTEN                            0                                 4096                                                                  [::]:443                                                                [::]:*

So far, only the 127.0.0.1:8080 server shows up from inside the docker container.

VyOS program setup

Docker network setup for VyOS

Enable IPv6 for VyOS

  1. Enter root with sudo -i
  2. Stop docker daemon with systemctl stop docker.
  3. Run cat /etc/docker/daemon.json. If that command fails, then continue normally.
  4. create a daemon.json file in the directory /etc/docker with the command echo -e '{\n "ipv6": true,\n "fixed-cidr-v6": "2001:db8::/64"\n}' > /etc/docker/daemon.json.
  5. Start the docker daemon with systemctl start docker.
  6. Exit root user with exit.
  7. If step 3 runs, and a /etc/docker/daemon.json is found, then simply add these 2 lines of json to the file:
{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8::/64"
}

Create container network interface

In order to get the Docker container to communicate with the host on the network interface that links to the engineering entwork, a macvlan driver must be used.
This command creates the docker macvlan interface.

docker network create -d macvlan --subnet=10.151.192.0/20 --gateway=10.151.192.1 -o parent=enp88s0 macvlan-vyos-driver

Host network setup for VyOS

The host OS now needs to create an interface to connect the container to the outside network.
Run this command to generate the macvlan interface on the host OS:

# create the macvlan device
sudo ip link add demo-nuc-vyos link enp88s0 type macvlan mode bridge
# Assign the device an IP address
sudo ip addr add 10.151.200.182/20 dev demo-nuc-vyos
# Bring up the interface
sudo ip link set demo-nuc-vyos up

Note: enp88s0 is the host network interface connected to the internet.

VyOS setup docker container

Create VyOS from ISO image

Run these commands to create the docker image.

mkdir vyos && pushd vyos
wget https://s3-us.vyos.io/rolling/current/vyos-1.4-rolling-202305010317-amd64.iso
# shortname="1.4-rolling-202305010317"
# Grab the latest vyos ISO file by download date to the filesystem.
isofile=$(ls -t | grep "vyos-" | head -n 1)
# The name without cpu architecture nor vyos header
shortname=$(echo $isofile | sed 's/vyos-//g' | sed 's/-amd64.iso//g')
# Now for the rest of the script that uses these variables
mkdir rootfs
sudo mount -o loop $isofile rootfs
# sudo apt-get install -y squashfs-tools
mkdir unsquashfs
sudo unsquashfs -f -d unsquashfs/ rootfs/live/filesystem.squashfs
sudo tar -C unsquashfs -c . | docker import - vyos:$shortname
sudo umount rootfs
popd
# Deleting the directory is optional
sudo rm -rf vyos

Run this command to create the docker container.
This command should be run in the same terminal as the previous commands.

# Create the container without the macvlan and then attach the macvlan after the fact
docker run -d --rm -p 443:443/udp -p 443:443 --name vyos --privileged -v /lib/modules:/lib/modules -v $(pwd)/config:/config vyos:1.4-rolling-202305010317 /sbin/init
# Attach after the fact
docker network connect macvlan-vyos-driver vyos
# Only when the macvlan is attached after the fact do I see the ports exposed in "docker port".

Then run this command to enter the docker container inside the VyOS process.

docker exec -ti vyos su vyos

Configure HTTP API

Enter the VyOS process with docker exec -ti vyos su vyos.
Then run these commands:

cd ~
mkdir -p config
pushd config
configure
set service https api debug
set service https api keys id theid key thepass
commit
save
exit

Validate HTTP API is enabled

Enabled for localhost

Query the VyOS container to make sure the HTTP API is listening for requests with this curl command:

vyos@84fa1e0505fa:/$ curl --location --request POST 'http://127.0.0.1:8080/retrieve' --form data='{"op": "showConfig", "path": []}' --form key='thepass'
{"success": true, "data": {"interfaces": {"loopback": {"lo": {}}}, "service": {"https": {"api": {"debug": {}, "keys": {"id": {"theid": {"key": "thepass"}}}}}, "ntp": {"allow-client": {"address": ["0.0.0.0/0", "::/0"]}, "server": {"time1.vyos.net": {}, "time2.vyos.net": {}, "time3.vyos.net": {}}}}, "system": {"config-management": {"commit-revisions": "100"}, "conntrack": {"modules": {"ftp": {}, "h323": {}, "nfs": {}, "pptp": {}, "sip": {}, "sqlnet": {}, "tftp": {}}}, "console": {"device": {"ttyS0": {"speed": "115200"}}}, "host-name": "vyos", "login": {"user": {"vyos": {"authentication": {"encrypted-password": "$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/", "plaintext-password": ""}}}}, "syslog": {"global": {"facility": {"all": {"level": "info"}, "protocols": {"level": "debug"}}}}}}, "error": null}
vyos@84fa1e0505fa:/$

Enabled for the docker host

Query the docker host to make sure the HTTP API is listening for requests with this curl command:

user@device:~$ curl --location -k --request POST 'https://10.151.200.182/retrieve' --form data='{"op": "showConfig", "path": []}' --form key='thepass'
curl: (7) Failed to connect to 10.151.200.182 port 443: Connection refused
user@device:~$

And that is where I am getting the failure. Below I have provided the network interface configuration for the docker host:

user@device:~$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: enp88s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 1c:69:7a:ad:d5:67 brd ff:ff:ff:ff:ff:ff
    inet 10.151.192.144/20 brd 10.151.207.255 scope global dynamic noprefixroute enp88s0
       valid_lft 83777sec preferred_lft 83777sec
    inet6 fe80::8a6a:f833:d555:cae/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: enx00e04c6803c9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:e0:4c:68:03:c9 brd ff:ff:ff:ff:ff:ff
4: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 60:e3:2b:35:12:31 brd ff:ff:ff:ff:ff:ff
    altname wlp0s20f3
    inet 10.151.193.171/20 brd 10.151.207.255 scope global dynamic noprefixroute wlo1
       valid_lft 83775sec preferred_lft 83775sec
    inet6 fe80::564d:b959:2b6b:9e0a/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:37:21:d8:4a brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 2001:db8::1/64 scope global
       valid_lft forever preferred_lft forever
    inet6 fe80::42:37ff:fe21:d84a/64 scope link
       valid_lft forever preferred_lft forever
    inet6 fe80::1/64 scope link
       valid_lft forever preferred_lft forever
6: demo-nuc-vyos@enp88s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 72:69:5b:ad:2a:0b brd ff:ff:ff:ff:ff:ff
    inet 10.151.200.182/20 scope global demo-nuc-vyos
       valid_lft forever preferred_lft forever
    inet6 fe80::7069:5bff:fead:2a0b/64 scope link
       valid_lft forever preferred_lft forever
9: vethb9a86e7@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 42:24:0f:66:09:8f brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::4024:fff:fe66:98f/64 scope link
       valid_lft forever preferred_lft forever

And here is the ip addr show from inside the container:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 fe80::200:ff:fe00:0/64 scope link
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
8: eth0@if9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2001:db8::242:ac11:2/64 scope global nodad
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link
       valid_lft forever preferred_lft forever
10: eth1@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:0a:97:c0:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.151.192.2/20 brd 10.151.207.255 scope global eth1
       valid_lft forever preferred_lft forever

I have also validated the ports are open with docker network:

user@device:~$ docker port vyos
443/tcp -> 0.0.0.0:443
443/tcp -> [::]:443
443/udp -> 0.0.0.0:443
443/udp -> [::]:443

I can also see that the container has a proper external subnet connection because the VyOS commands in configure mode show it:

vyos@84fa1e0505fa# run show interfaces
Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
Interface        IP Address                        S/L  Description
---------        ----------                        ---  -----------
eth0             172.17.0.2/16                     u/u
                 2001:db8::242:ac11:2/64
eth1             10.151.192.2/20                   u/u
lo               127.0.0.1/8                       u/u
                 ::1/128
[edit]
vyos@84fa1e0505fa#

The 10.151.192.0/20 subnet still needs access to the HTTP api.
What am I doing wrong? What else shoul I be trying?

You send request to 10.151.200.182 but it seems you don’t have this address on the VyOS instance

eth1             10.151.192.2/20

Even when I try that IP address on the docker host, I still don’t get a valid response.

user@host:~$ curl --location -k --request POST 'https://10.151.192.2/retrieve' --form data='{"op": "showConfig", "path": []}' --form key='thepass'
curl: (7) Failed to connect to 10.151.192.2 port 443: Connection refused

I checked ss -a again and I don’t see a port 443 open (inside the VyOS image).
I run the same check on the docker host and I see that the 443 port connections are labeled UNCONN as shown here (look towards the bottom):

 ss -a | grep 443
u_dgr              UNCONN              0                    0                                                                          /run/wpa_supplicant/wlo1 34432                                            * 0
u_str              ESTAB               0                    0                                                                       /run/systemd/journal/stdout 31443                                            * 32203
u_str              ESTAB               0                    0                                                                       /run/systemd/journal/stdout 44399                                            * 39753
u_str              ESTAB               0                    0                                                                       /run/systemd/journal/stdout 44396                                            * 39705
u_str              ESTAB               0                    0                                                                                                 * 39753                                            * 44399
u_str              ESTAB               0                    0                                                                                                 * 32364                                            * 34430
u_str              ESTAB               0                    0                                                                                                 * 39443                                            * 41153
u_str              ESTAB               0                    0                                                                                                 * 32203                                            * 31443
u_str              ESTAB               0                    0                                                                                                 * 44353                                            * 40693
u_str              ESTAB               0                    0                                                                             @/tmp/dbus-iHfFbFPbxa 44392                                            * 43425
u_str              ESTAB               0                    0                                                                 @/dbus-vfs-daemon/socket-tafk0Isn 40693                                            * 44353
u_str              ESTAB               0                    0                                                                                @/tmp/.X11-unix/X0 41153                                            * 39443
u_str              ESTAB               0                    0                                                                       /run/dbus/system_bus_socket 34430                                            * 32364
u_str              ESTAB               0                    0                                                                                                 * 43425                                            * 44392
u_str              ESTAB               0                    0                                                                                                 * 39705                                            * 44396
udp                UNCONN              0                    0                                                                                           0.0.0.0:443                                        0.0.0.0:*
udp                UNCONN              0                    0                                                                                              [::]:443                                           [::]:*

Does this mean that the HTTP server is disconnected from the docker host?

Interestingly enough, running the curl command inside the docker container returns this output:

vyos@84fa1e0505fa:/$ curl --location -k --request POST 'https://10.151.192.2/retrieve' --form data='{"op": "showConfig", "path": []}' --form key='thepass'
curl: (7) Failed to connect to 10.151.192.2 port 443 after 0 ms: Couldn't connect to server

I should also mention I added a virtual-host in hopes that might force the port to be exposed. I don’t think that helped.

 service {
     https {
         api {
             debug
             keys {
                 id theid {
                     key thepass
                 }
             }
         }
         virtual-host r1 {
             listen-port 443
         }
     }
     ntp {
         allow-client {
             address 0.0.0.0/0
             address ::/0
         }
         server time1.vyos.net {
         }
         server time2.vyos.net {
         }
         server time3.vyos.net {
         }
     }
     ssh {
         port 22
     }
 }

Which reminds me - how do you remove a configuration parameter? Not the most important question, but it would be helpful to know.

I have a few other thoughts here
Is it possible that there is a firewall blocking the request, even though I am running curl on the docker container host?
Should I revert to an earlier ISO release?
Do I need to edit the routing table? I noticed that the GUI for the Ubuntu host is showing “Connection failed” popups, even though I can ping google from both the docker host and from inside the container.

Thanks

I have been doing some exploring around VyOS. I have never used it before so I figured I should figure out how VyOS natively presents port usage information. I noticed that in regular run mode I can run show ip ports and I see all ports in use and where they are used:

sudo: unable to resolve host 589b91c590dd: System error
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      1400/python3
tcp        0      0 127.0.0.1:2617          0.0.0.0:*               LISTEN      1728/bfdd
tcp        0      0 127.0.0.1:2616          0.0.0.0:*               LISTEN      1725/staticd
tcp        0      0 127.0.0.1:2613          0.0.0.0:*               LISTEN      1718/eigrpd
tcp        0      0 127.0.0.1:2612          0.0.0.0:*               LISTEN      1716/ldpd
tcp        0      0 127.0.0.1:2609          0.0.0.0:*               LISTEN      1712/babeld
tcp        0      0 127.0.0.1:2608          0.0.0.0:*               LISTEN      1710/isisd
tcp        0      0 127.0.0.1:2605          0.0.0.0:*               LISTEN      1691/bgpd
tcp        0      0 127.0.0.1:2604          0.0.0.0:*               LISTEN      1704/ospfd
tcp        0      0 127.0.0.1:2601          0.0.0.0:*               LISTEN      1686/zebra
tcp        0      0 127.0.0.1:2602          0.0.0.0:*               LISTEN      1698/ripd
tcp        0      0 127.0.0.11:45863        0.0.0.0:*               LISTEN      -
tcp6       0      0 ::1:2606                :::*                    LISTEN      1707/ospf6d
tcp6       0      0 ::1:2603                :::*                    LISTEN      1701/ripngd
udp        0      0 0.0.0.0:123             0.0.0.0:*                           1011/chronyd
udp        0      0 127.0.0.1:323           0.0.0.0:*                           1011/chronyd
udp        0      0 0.0.0.0:3784            0.0.0.0:*                           1728/bfdd
udp        0      0 0.0.0.0:4784            0.0.0.0:*                           1728/bfdd
udp        0      0 127.0.0.11:60901        0.0.0.0:*                           -
udp6       0      0 :::123                  :::*                                1011/chronyd
udp6       0      0 ::1:323                 :::*                                1011/chronyd
udp6       0      0 :::3784                 :::*                                1728/bfdd
udp6       0      0 :::3785                 :::*                                1728/bfdd
udp6       0      0 :::4784                 :::*                                1728/bfdd

From what I understand of http, this result means that port 443 isn’t being used to respond to http/s requests. I now need to figure out how to make VyOS respond to my http requests.

I also did more digging and I found a tool called squid that can provide proxy servers for http requests. I am not an expert in this tech, but squid sounds like the tool I need to pipe 127.0.0.1:8080 out of port 443 for https. I also recently learned that using https automatically uses port 443. I did further poking around and I see that squid is already available in the VyOS image and that it is sitting unused. If I am not mistaken, the May 1st VyOS image does not have port 443 allowed, so I think my next move is to figure out how to enable the squid proxy server. If I am wrong anywhere in any of my posts, feel free to tell me.

Try the image without docker
All requests will work without any issues by https

@Viacheslav, do you mean install VyOS inside of Ubuntu as a running process, or as an entirely separate OS and hardware platform? My goal is to install VyOS on a Ubuntu host. This means that Ubuntu should still run as Ubuntu, but VyOS operates in the foreground. Are there any restrictions to this goal I should know? Is this a supported configuration? Which set of instructions should I follow? I will peruse the VyOS documentation further on this subject.

I am new to proxy servers, but it looks like Docker requires multiple configuration parameters to enable proxy connections:

https://elegantinfrastructure.com/docker/ultimate-guide-to-docker-http-proxy-configuration/\
https://docs.docker.com/network/proxy/

Has anybody else here configured a proxy with docker? If I had to guess, the proxy server needs to live inside the docker container and run with systemctl.

I formatted a USB thumb drive with the May 5th image rolling image of VyOS to boot from a live disk. I am getting errors with that methodology as well.

error: bad shim shim signature.
error: you need to load the kernel first.

It looks like this issue is caused by secure boot being enabled on my device.
I will continue to investigate booting from ISO to see if this will work on the Intel NuC sitting at my desk.
Then I will try to set up the REST API.

Playing around with the ISO install also makes me think that the curl call needs a user login and password to solve the original problem of networking through the docker container.

Edit 1:

I booted the VyOS image from an ISO file loaded onto a thumb drive on an Intel NuC. I then proceeded with the configuration calls to enable the REST api. I then ran the following curl command from a WSL instance on the same network as the WLAN port of the Intel NuC.

curl --location -k --request POST 'https://10.151.192.144/retrieve' --form data='{"op": "showConfig", "path": []}' --form key='thepass'

I was able to get a valid response from the REST server:

{"success": true, "data": {"interfaces": {"ethernet": {"eth1": {"hw-id": "1c:69:7a:ad:d5:67"}, "eth2": {"hw-id": "00:e0:4c:68:03:c9"}}, "loopback": {"lo": {}}, "wireless": {"wlan0": {"hw-id": "60:e3:2b:35:12:31", "physical-device": "phy0"}}}, "service": {"https": {"api": {"debug": {}, "keys": {"id": {"theid": {"key": "thepass"}}}}}, "ntp": {"allow-client": {"address": ["0.0.0.0/0", "::/0"]}, "server": {"time1.vyos.net": {}, "time2.vyos.net": {}, "time3.vyos.net": {}}}}, "system": {"config-management": {"commit-revisions": "100"}, "conntrack": {"modules": {"ftp": {}, "h323": {}, "nfs": {}, "pptp": {}, "sip": {}, "sqlnet": {}, "tftp": {}}}, "console": {"device": {"ttyS0": {"speed": "115200"}}}, "host-name": "vyos", "login": {"user": {"vyos": {"authentication": {"encrypted-password": "$6$QxPS.uk6mfo$9QBSo8u1FkH16gMyAVhus6fU3LOzvLR9Z9.82m3tiHFAxTtIkhaZSWssSgzt4v4dGAL8rhVQxTg0oAG9/q11h/", "plaintext-password": ""}}}}, "syslog": {"global": {"facility": {"all": {"level": "info"}, "protocols": {"level": "debug"}}}}}}, "error": null}

The original problem of exposing the REST API with VyOS in a docker container remains unsolved. This ISO thumb drive boot configuration will not work in the long term for the automated network testing I need to do, but I at least can practice writing python3 requests calls for the automated tests I need to write.

Edit 2:

I am noticing that, in the json returned from the showConfig call above, there are ethernet interfaces defined. I am beginning to think that my original problem stems from the fact that there have to be network interfaces defined besides localhost before the VyOS REST api will function. I did not know that the docker image ignored creating internal network interfaces in the VyOS config when ip addr show presents valid network interfaces.

I have done more digging into the docker run variant of VyOS. I figured out that the http api lives in

/usr/libexec/vyos/services$ ls
api  vyos-configd  vyos-hostsd  vyos-http-api-server

I checked the running processes for python instances:

vyos@1ae7d5760bb7:/usr/libexec/vyos/services$ ps aux | grep "python"
root          49  0.0  0.1 320696 79404 ?        Ssl  17:37   0:00 /usr/bin/python3 -u /usr/libexec/vyos/services/vyos-configd
root          50  0.0  0.0 120200 28788 ?        Ssl  17:37   0:00 /usr/bin/python3 -u /usr/libexec/vyos/services/vyos-hostsd
vyos        2742  0.0  0.0   3324  1572 pts/0    S+   18:07   0:00 grep python

I went to enable the http api and I now see the process:

vyos@1ae7d5760bb7:/usr/share/vyos-http-api-tools/bin$ ps aux | grep "python"
root          51  0.0  0.1 169952 75648 ?        Ssl  18:16   0:00 /usr/bin/python3 -u /usr/libexec/vyos/services/vyos-configd
root          52  0.0  0.0 120164 28624 ?        Ssl  18:16   0:00 /usr/bin/python3 -u /usr/libexec/vyos/services/vyos-hostsd
root        1771  0.4  0.0 161412 55460 ?        Ssl  18:38   0:00 /usr/share/vyos-http-api-tools/bin/python3 /usr/libexec/vyos/services/vyos-http-api-server
vyos        1926  0.0  0.0   3324  1576 pts/0    S+   18:40   0:00 grep python

This leads me to believe that the container is blocking the api from going outside of the container. Now I just need to figure out why.

Edit 1:

I can see that FASTApi builds the http server. I did some looking up and from this link:

https://fastapi.tiangolo.com/deployment/docker/#dockerfile

I can see that uvicorn must be specifically enabled to get the web server to work in docker containers. Looking at the github for VyOS here:

https://github.com/vyos/vyos-build/blob/current/docker/Dockerfile

It is clear that the uvicorn is not actually enabled to operate in the Dockerfile as outlined in the fastapi documentation. This leads me to believe that the Dockerfile needs to be edited to allow the http api to function properly. I think a new docker image needs to be created from scratch to test out this theory.

Hi, I have the same problem as you, I need to configure the firewall from outside docker. Have you managed to access the API from outside?

Hi, finally i have solved the problem, basically i need add the following rules to the firewall:

set firewall name ALLOW_API rule 10 action ‘accept’
set firewall name ALLOW_API rule 10 protocol ‘tcp’
set firewall name ALLOW_API rule 10 destination port ‘8080’
set interfaces ethernet eth0 firewall in name ‘ALLOW_API’

Then you can do this curl in your host with the local host:

curl --location --request POST ‘http://localhost:8080/retrieve’ --form data=‘{“op”: “showConfig”, “path”: }’ --form key=‘YOUR-KEY-VYOS’

Hi @diegosg - Thank you so much for sharing your solution! It’s great to hear that you were able to resolve the issue. This will definitely come handy for anyone else encountering a similar problem.