diff --git a/bubble-server/src/main/java/bubble/cloud/compute/ComputeServiceDriver.java b/bubble-server/src/main/java/bubble/cloud/compute/ComputeServiceDriver.java index c96e42a8..f7eba720 100644 --- a/bubble-server/src/main/java/bubble/cloud/compute/ComputeServiceDriver.java +++ b/bubble-server/src/main/java/bubble/cloud/compute/ComputeServiceDriver.java @@ -72,4 +72,7 @@ public interface ComputeServiceDriver extends CloudServiceDriver, RegionalServic default void addLaunchContext(Map ctx) { addLaunchContext(ctx, ""); } default void addLaunchContext(Map ctx, String prefix) {} + default String getNodeIp4(BubbleNode node) { return node.getIp4(); } + default String getNodeIp6(BubbleNode node) { return node.getIp6(); } + } diff --git a/bubble-server/src/main/java/bubble/cloud/compute/docker/DockerComputeDriver.java b/bubble-server/src/main/java/bubble/cloud/compute/docker/DockerComputeDriver.java index fafdd279..2ed69bfb 100644 --- a/bubble-server/src/main/java/bubble/cloud/compute/docker/DockerComputeDriver.java +++ b/bubble-server/src/main/java/bubble/cloud/compute/docker/DockerComputeDriver.java @@ -39,6 +39,8 @@ import static org.cobbzilla.util.io.FileUtil.abs; import static org.cobbzilla.util.io.StreamUtil.loadResourceAsStream; import static org.cobbzilla.util.io.StreamUtil.stream2file; import static org.cobbzilla.util.json.JsonUtil.json; +import static org.cobbzilla.util.network.NetworkUtil.IPv4_LOCALHOST; +import static org.cobbzilla.util.network.NetworkUtil.IPv6_LOCALHOST; import static org.cobbzilla.util.system.Sleep.sleep; @Slf4j @@ -90,9 +92,10 @@ public class DockerComputeDriver extends ComputeServiceDriverBase { private final Map> portMappings = new ConcurrentHashMap<>(); - @Override public int getSshPort(BubbleNode node) { - return portMappings.get(node.getUuid()).get(22); - } + @Override public int getSshPort(BubbleNode node) { return portMappings.get(node.getUuid()).get(22); } + + @Override public String getNodeIp4(BubbleNode node) { return IPv4_LOCALHOST; } + @Override public String getNodeIp6(BubbleNode node) { return IPv6_LOCALHOST; } @Getter(lazy=true) private final DockerClient dockerClient = initDockerClient(); private DockerClient initDockerClient() { @@ -182,9 +185,12 @@ public class DockerComputeDriver extends ComputeServiceDriverBase { final Integer adminPort = portMap.get(8090); if (adminPort == null) return die("start("+node.id()+"): admin port mapping not found in port map: "+json(portMap)); + final String ip4 = nodeDAO.randomLocalhostIp4(); + final String ip6 = nodeDAO.randomLocalhostIp6(); return node.setState(BubbleNodeState.running) .setAdminPort(adminPort) - .setIp4(nodeDAO.randomLocalhostIp4()) + .setIp4(ip4) + .setIp6(ip6) .setFqdn(node.getIp4()); } } diff --git a/bubble-server/src/main/java/bubble/dao/cloud/BubbleNodeDAO.java b/bubble-server/src/main/java/bubble/dao/cloud/BubbleNodeDAO.java index 8b6d46c2..b2e1e08d 100644 --- a/bubble-server/src/main/java/bubble/dao/cloud/BubbleNodeDAO.java +++ b/bubble-server/src/main/java/bubble/dao/cloud/BubbleNodeDAO.java @@ -21,7 +21,7 @@ import static bubble.ApiConstants.ROOT_NETWORK_UUID; import static bubble.ApiConstants.newNodeHostname; import static bubble.model.cloud.BubbleNodeState.running; import static org.cobbzilla.util.daemon.ZillaRuntime.die; -import static org.cobbzilla.util.network.NetworkUtil.isLocalIpv4; +import static org.cobbzilla.util.network.NetworkUtil.*; import static org.cobbzilla.wizard.resources.ResourceUtil.invalidEx; import static org.hibernate.criterion.Restrictions.isNotNull; @@ -110,23 +110,31 @@ public class BubbleNodeDAO extends AccountOwnedEntityDAO { public List findWithIp4() { return list(criteria().add(isNotNull("ip4"))); } - public BubbleNode findByIp4(String ip4) { return isLocalIpv4(ip4) ? null : findByUniqueField("ip4", ip4); } + public BubbleNode findByIp4(String ip4) { return isLocalIpv4(ip4) ? null : _findByIp4(ip4); } + + public BubbleNode _findByIp4(String ip4) { return findByUniqueField("ip4", ip4); } + public BubbleNode _findByIp6(String ip6) { return findByUniqueField("ip6", ip6); } public String randomLocalhostIp4 () { // first try a random number in the last slot int x = RandomUtils.nextInt(1, 255); String testIp = "127.0.0." + x; - if (findByIp4(testIp) == null) return testIp; - - // keep trying random numbers, incrementing the other octets - for (int i=0; i<254; i++) { - for (int j=0; j<254; j++) { - x = RandomUtils.nextInt(1, 255); - testIp = "127."+i+"."+j+"."+x; - if (findByIp4(testIp) == null) return testIp; - } + if (_findByIp4(testIp) == null) return testIp; + + // keep trying random numbers + for (int i=0; i<100; i++) { + testIp = randomLocalIp4(); + if (_findByIp4(testIp) == null) return testIp; } return die("randomLocalhostIp4: ran out of tries!"); } + public String randomLocalhostIp6 () { + for (int i=0; i<100; i++) { + final String testIp = randomLocalIp6(); + if (_findByIp6(testIp) == null) return testIp; + } + return die("randomLocalhostIp6: ran out of tries!"); + } + } diff --git a/bubble-server/src/main/java/bubble/server/listener/BubbleFirstTimeListener.java b/bubble-server/src/main/java/bubble/server/listener/BubbleFirstTimeListener.java index f6dfbbaa..81e4b8d8 100644 --- a/bubble-server/src/main/java/bubble/server/listener/BubbleFirstTimeListener.java +++ b/bubble-server/src/main/java/bubble/server/listener/BubbleFirstTimeListener.java @@ -55,11 +55,11 @@ public class BubbleFirstTimeListener extends RestServerLifecycleListenerBase= 4096) return (int) (((double) memoryMB) * 0.6d); if (memoryMB >= 2048) return (int) (((double) memoryMB) * 0.5d); if (memoryMB >= 1024) return (int) (((double) memoryMB) * 0.24d); + // no nodes are this small, API probably would not start, not enough memory - return (int) (((double) memoryMB) * 0.19d); + // set floor at 200MB, might be able to go lower. + return Math.max(200, (int) (((double) memoryMB) * 0.19d)); } private boolean shouldEnableOpenApi(AnsibleInstallType installType, ComputeNodeSize nodeSize) { diff --git a/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java b/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java index 18b87520..b1a20bc0 100644 --- a/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java +++ b/bubble-server/src/main/java/bubble/service/cloud/StandardNetworkService.java @@ -304,7 +304,7 @@ public class StandardNetworkService implements NetworkService { + "-o StrictHostKeyChecking=no " + "-o PreferredAuthentications=publickey " + "-i " + abs(sshKeyFile); - final String sshTarget = node.getUser() + "@" + node.getIp4(); + final String sshTarget = node.getUser() + "@" + computeDriver.getNodeIp4(node); boolean setupOk = false; final String nodeUser = node.getUser(); diff --git a/bubble-server/src/main/resources/ansible/install_local.sh.hbs b/bubble-server/src/main/resources/ansible/install_local.sh.hbs index 56bb90be..afa14660 100644 --- a/bubble-server/src/main/resources/ansible/install_local.sh.hbs +++ b/bubble-server/src/main/resources/ansible/install_local.sh.hbs @@ -87,7 +87,7 @@ cd "${ANSIBLE_DIR}" && \ . ./venv/bin/activate && \ pip3 install ansible && \ ansible-playbook ${SKIP_TAGS} --inventory ./hosts ./playbook.yml 2>&1 | tee ${LOG} \ -|| die "Error running ansible. journalctl -xe = $(journalctl -xe | tail -n 50) ___dhparams=$(cat /etc/nginx/dhparams.pem)" +|| die "Error running ansible. journalctl -xe = $(journalctl -xe | tail -n 50) ___dhparams=$(if [[ -f /etc/nginx/dhparams.pem ]] ; then cat /etc/nginx/dhparams.pem ; else echo "(does not exist)" ; fi)" # lockout the node that started us cat /dev/null > "${AUTH_KEYS}" || die "Error truncating ${AUTH_KEYS} file" diff --git a/bubble-server/src/main/resources/ansible/roles/bubble/files/bubble_role.json b/bubble-server/src/main/resources/ansible/roles/bubble/files/bubble_role.json index 593c0228..756ab1a3 100644 --- a/bubble-server/src/main/resources/ansible/roles/bubble/files/bubble_role.json +++ b/bubble-server/src/main/resources/ansible/roles/bubble/files/bubble_role.json @@ -19,7 +19,7 @@ {"name": "db_name", "value": "bubble"}, {"name": "db_key", "value": "[[dbEncryptionKey]]"}, {"name": "letsencrypt_email", "value": "[[configuration.letsencryptEmail]]"}, - {"name": "openapi_contact_email", "value": "openapi_contact_email"}, + {"name": "openapi_contact_email", "value": "[[[openapi_contact_email]]]"}, {"name": "is_fork", "value": "[[fork]]"}, {"name": "restore_key", "value": "[[restoreKey]]"}, {"name": "restore_timeout", "value": "[[restoreTimeoutSeconds]]"}, diff --git a/bubble-server/src/main/resources/ansible/roles/bubble/templates/bubble.env.j2 b/bubble-server/src/main/resources/ansible/roles/bubble/templates/bubble.env.j2 index 74b7aff4..b592d470 100644 --- a/bubble-server/src/main/resources/ansible/roles/bubble/templates/bubble.env.j2 +++ b/bubble-server/src/main/resources/ansible/roles/bubble/templates/bubble.env.j2 @@ -22,4 +22,4 @@ export APP_LINK_MACOSX={{ app_link_macosx }} export APP_LINK_LINUX={{ app_link_linux }} export CERT_VALIDATION_HOST={{ cert_validation_host }} -export OPENAPI_CONTACT_EMAIL={{ openapi_contact_email }} \ No newline at end of file +export OPENAPI_CONTACT_EMAIL={{ openapi_contact_email }} diff --git a/bubble-server/src/main/resources/ansible/roles/finalizer/files/bubble_role.json b/bubble-server/src/main/resources/ansible/roles/finalizer/files/bubble_role.json index 40a2f9c8..b5989792 100644 --- a/bubble-server/src/main/resources/ansible/roles/finalizer/files/bubble_role.json +++ b/bubble-server/src/main/resources/ansible/roles/finalizer/files/bubble_role.json @@ -7,7 +7,8 @@ {"name": "install_type", "value": "[[installType]]"}, {"name": "bubble_java_opts", "value": "-XX:MaxRAM=[[jvmMaxRamMB]]m"}, {"name": "total_memory", "value": "[[nodeSize.memoryMB]]"}, - {"name": "cert_name", "value": "bubble-[[network.shortId]]"} + {"name": "cert_name", "value": "bubble-[[network.shortId]]"}, + {"name": "enable_nginx", "value": "[[bubble_deploy_nginx]]"} ], "optionalConfigNames": ["restore_key"] } \ No newline at end of file diff --git a/bubble-server/src/main/resources/ansible/roles/finalizer/tasks/main.yml b/bubble-server/src/main/resources/ansible/roles/finalizer/tasks/main.yml index fd71401d..df77a66a 100644 --- a/bubble-server/src/main/resources/ansible/roles/finalizer/tasks/main.yml +++ b/bubble-server/src/main/resources/ansible/roles/finalizer/tasks/main.yml @@ -45,21 +45,30 @@ - name: Ensure nginx dhparams.pem file exists and is valid shell: /usr/local/bin/init_dhparams.sh wait + when: enable_nginx - name: Ensure nginx required files exist shell: /usr/local/bin/ensure_file_exists.sh {{ item }} 300 with_items: - /etc/letsencrypt/live/{{ server_alias }}/fullchain.pem - /etc/letsencrypt/live/{{ server_name }}/fullchain.pem + when: enable_nginx - name: Ensure nginx is restarted service: name: nginx state: restarted + when: enable_nginx + +- name: stat /usr/share/unattended-upgrades/20auto-upgrades-disabled + stat: + path: /usr/share/unattended-upgrades/20auto-upgrades-disabled + register: upgrades_disabled_file - name: Enable unattended upgrades shell: systemctl start unattended-upgrades become: yes + when: upgrades_disabled_file.stat.exists - name: Ensure authorized SSH keys are up-to-date shell: su - bubble bash -c "touch /home/bubble/.refresh_ssh_keys" diff --git a/bubble-server/src/main/resources/ansible/roles/nginx/files/bubble_role.json b/bubble-server/src/main/resources/ansible/roles/nginx/files/bubble_role.json index 59055078..eaeb8de7 100644 --- a/bubble-server/src/main/resources/ansible/roles/nginx/files/bubble_role.json +++ b/bubble-server/src/main/resources/ansible/roles/nginx/files/bubble_role.json @@ -6,6 +6,7 @@ {"name": "letsencrypt_email", "value": "[[configuration.letsencryptEmail]]"}, {"name": "ssl_port", "value": "[[node.sslPort]]"}, {"name": "admin_port", "value": "[[node.adminPort]]"}, - {"name": "install_type", "value": "[[installType]]"} + {"name": "install_type", "value": "[[installType]]"}, + {"name": "enable_nginx", "value": "[[bubble_deploy_nginx]]"} ] } \ No newline at end of file diff --git a/bubble-server/src/main/resources/ansible/roles/nginx/tasks/main.yml b/bubble-server/src/main/resources/ansible/roles/nginx/tasks/main.yml index 9eddb966..f7c46627 100644 --- a/bubble-server/src/main/resources/ansible/roles/nginx/tasks/main.yml +++ b/bubble-server/src/main/resources/ansible/roles/nginx/tasks/main.yml @@ -5,13 +5,17 @@ service: name: nginx state: stopped + when: enable_nginx - name: Create dhparam nginx conf template: src: stronger_dhparams.conf dest: /etc/nginx/conf.d/stronger_dhparams.conf + when: enable_nginx - include: site.yml + when: enable_nginx - name: Init certbot shell: init_certbot.sh {{ letsencrypt_email }} {{ server_name }} {{ server_alias }} + when: enable_nginx diff --git a/bubble-server/src/main/resources/bubble/host-prefixes.txt b/bubble-server/src/main/resources/bubble/host-prefixes.txt index 8eb6a9e6..aae08460 100644 --- a/bubble-server/src/main/resources/bubble/host-prefixes.txt +++ b/bubble-server/src/main/resources/bubble/host-prefixes.txt @@ -3321,7 +3321,6 @@ exude exuls exult exurb -eyass eyers eying eyots @@ -3348,7 +3347,6 @@ faery faffs fagin faiks -fails faine fains faint @@ -3369,7 +3367,6 @@ fanga fango fangs fanks -fanny fanon fanos fanum @@ -3425,7 +3422,6 @@ feces fecht fecit fecks -fedex feebs feeds feels @@ -3513,7 +3509,6 @@ fifth fifty fight figos -fiked filar filed filer @@ -3526,9 +3521,7 @@ fills filly filmi films -filmy filos -filth filum final finca @@ -3554,10 +3547,8 @@ firns firry first firth -fiscs fishy fisks -fists fisty fitch fitly @@ -3820,7 +3811,6 @@ fuffs fuffy fugal fugle -fugly fugus fujis fulls @@ -3861,9 +3851,6 @@ fuzee fuzes fuzil fuzzy -fyces -fyked -fykes fyles fyrds fytte diff --git a/bubble-server/src/main/resources/packer/roles/finalizer/tasks/main.yml b/bubble-server/src/main/resources/packer/roles/finalizer/tasks/main.yml index baef91a5..83b24759 100644 --- a/bubble-server/src/main/resources/packer/roles/finalizer/tasks/main.yml +++ b/bubble-server/src/main/resources/packer/roles/finalizer/tasks/main.yml @@ -1,10 +1,6 @@ # # Copyright (c) 2020 Bubble, Inc. All rights reserved. For personal (non-commercial) use, see license: https://getbubblenow.com/bubble-license/ # -- name: Touch first-time setup file - shell: su - bubble bash -c "if [[ ! -f /home/bubble/first_time_marker ]] ; then echo -n install > /home/bubble/first_time_marker ; fi" - when: restore_key is not defined - - name: Install copy_certs_to_bubble.sh helper copy: src: copy_certs_to_bubble.sh diff --git a/utils/cobbzilla-utils b/utils/cobbzilla-utils index e0faad31..72e0962a 160000 --- a/utils/cobbzilla-utils +++ b/utils/cobbzilla-utils @@ -1 +1 @@ -Subproject commit e0faad31cb5cadfc000277d3f2052a57cb441b2d +Subproject commit 72e0962ac1defa342e8bad34044b56ee36817f52