sandstorm-io / sandstorm

Sandstorm is a self-hostable web productivity suite. It's implemented as a security-hardened web app package manager.
https://sandstorm.io
Other
6.74k stars 706 forks source link

Question: console app install #3379

Open Fohroer opened 4 years ago

Fohroer commented 4 years ago

Hello!

Is there a way to install Sandstorm.io without user interaction and then install apps from market without user interaction?

ocdtrekkie commented 4 years ago

The short answer is "not without some work". The long answer is:

Most of the install script can be automated, as it is for both testing/CI purposes and vagrant-spk. However, I do not believe there is a fully-automated way to install Sandstorm such that it is world-accessible. I believe the Sandcats.io setup flow requires manual interaction at present (something we should fix), and a more custom configuration likely requires more interaction. Note that updating the Sandcats installation flow is already something that needs to be looked at soon, due to https://sandstorm.io/news/2020-06-13-lets-encrypt

vagrant-spk uses install.sh -d -e which will run without user interaction. However, the defaults on the -d flag include enabling dev accounts, which use no password, and it uses local.sandstorm.io as the host configuration.

...But if you aren't trying to use Sandcats, you probably could write a script that would edit or replace the sandstorm.conf file and restart the service, as a way to configure Sandstorm after installation. It really depends what you are trying to use this for, I think.

So it's not the easiest, but it's doable.

App installation is a whole 'nother party, and again, I think it depends a little on your use case how complicated this is. We have no explicit command line command to do it from a command line. However, sandstorm mongo will let you modify the database, which is presumably what you'd have to do in your script. There are probably two ways you could tackle this: If you are only worried about scripting app installation for new users, you could add the apps to the "preinstalled apps" list in the database, and Sandstorm would happily install them for each new user. It'd probably be a little bit more complicated if you need to install a specific app for a specific user on command.

ocdtrekkie commented 4 years ago

I do think adjustments to the installer to better enable non-interactive setup of Sandstorm servers for non-dev use would be highly valuable to the project, as we could then offer one-click installers for cloud services and the like.

Fohroer commented 4 years ago

Let's talk about the usecase: service-provider wants to deliver apps through Sandstorm.io User byes a server with app he need, pays money and then automation goes:

  1. Create new VM
  2. Update OS
  3. Install Sandstorm.io
  4. Install app client needs
  5. Whitelist client's email for login purpose
  6. Send email to client to allow him to login.

Typically we need Wordpress, GitLab and some other CMS systems that we can manually pack into Sandstorm.io

kpreid commented 4 years ago

I do think adjustments to the installer to better enable non-interactive setup of Sandstorm servers for non-dev use would be highly valuable to the project, as we could then offer one-click installers for cloud services and the like.

One such cloud service is Linode, as previously discussed. Their interface supposes that a non-interactive script can perform the installation given some values entered in a form.

ocdtrekkie commented 4 years ago

That is definitely a case I think we'd like to enable/support. Would you be looking for Sandcats.io configuration, or your own wildcard DNS and certificate?

It looks like we actually have a couple more options than I realized (should read these docs sometimes!): https://docs.sandstorm.io/en/latest/administering/install-script/ where it looks like you may be able to stick the Sandcats domain in ahead of time?

Fohroer commented 4 years ago

One such cloud service is Linode, as previously discussed.

Does Linode use Sandstorm.io or their own system?

It looks like we actually have a couple more options than I realized (should read these docs sometimes!): https://docs.sandstorm.io/en/latest/administering/install-script/ where it looks like you may be able to stick the Sandcats domain in ahead of time?

Sandcats domain is OK for us.

ocdtrekkie commented 4 years ago

Okay. Sandcats is pretty straightforward to configure, including with HTTPS. The installer update I spoke of is now merged, #3383. So we probably need to see how many options existing environment variables aren't available for, and create the ability to set them. It is probably only a few.

Presumably we should have an installer flag like -o for one-click installer use, which is like -d but aims for a production one-click install, and only requires the desired Sandcats name and email address to be provided?

kpreid commented 4 years ago

One such cloud service is Linode, as previously discussed.

Does Linode use Sandstorm.io or their own system?

I meant that there could be a one-click installer for Sandstorm into a Linode virtual machine using Linode StackScripts (but nobody has written it yet). This does not have to do with providing installation of single apps, but of course there could be a variant with a preinstalled app.

Fohroer commented 4 years ago

Presumably we should have an installer flag like -o for one-click installer use, which is like -d but aims for a production one-click install, and only requires the desired Sandcats name and email address to be provided?

So, how much time you need to add console app install?

I meant that there could be a one-click installer for Sandstorm into a Linode virtual machine using Linode StackScripts (but nobody has written it yet). This does not have to do with providing installation of single apps, but of course there could be a variant with a preinstalled app.

It can be not only Linode. All service-providers which use virtualization, can provide VM templates. So it can be workaround with installed Sandstorm.io inside which we only need to configure to new domain. Is this possible?

zenhack commented 4 years ago

Note that you could automate most of the installation as-is by putting your responses to the prompts in a file and then feeding the file to install.sh on stdin:

$ curl http://install.sandstorm.io -o install.sh
$ chmod +x install.sh
$ ./install.sh < file-with-responses
ocdtrekkie commented 4 years ago

Ian's solution should work in the short term. I think it should be relatively trivial to update the install script to accept all inputs needed as environment variables, but I'm not sure how quickly I or someone else will get it done. I will try to find some time to look at it/play with it this upcoming week or so.

Fohroer commented 4 years ago

Note that you could automate most of the installation as-is by putting your responses to the prompts in a file and then feeding the file to install.sh on stdin

Sure, I know it. I can automate Sandstorm.io installation. My question is about automating apps installation. Can it be possible with file with responses?

Ian's solution should work in the short term. I think it should be relatively trivial to update the install script to accept all inputs needed as environment variables, but I'm not sure how quickly I or someone else will get it done. I will try to find some time to look at it/play with it this upcoming week or so.

I hope so. Can you show me an example of installation script with installing Sandstorm.io and then GitLab installation?

ocdtrekkie commented 4 years ago

@zenhack Do you know what the sandstorm mongo command would need to be to set GitLab as a preinstalled app?

zenhack commented 4 years ago

@ocdtrekkie, relevant bits of the code:

It should actually be pretty easy to plumb this (and other stuff like it) through to a CLI command; as part of the installer changes that @kentonv made recently we now have an rpc socket that lets us talk capnp to the JS side of things. I'm pretty excited about that actually, as it will make a lot of automation type things easier.

ocdtrekkie commented 4 years ago

I was just imagining we could get like an example like (NOT SURE IF THIS IS FORMATTED RIGHT AT ALL): echo 'db.settings.insert({_id: "preinstalledApps", value: {appId: "zx9d3pt0fjh4uqrprjftgpqfwgzp6y2ena6098ug3ctv37uv6kfh", status: "notReady", packageId: "128af0523f28d9e8ad195ca0927a4c73"}})' | sudo sandstorm mongo

ocdtrekkie commented 4 years ago

Which is to say I think we should still improve the install flow and implement more CLI commands for good configuration scripts, but I'm hoping to give a "it should work to do this now" option if we can?

zenhack commented 4 years ago

Quoting Jacob Weisz (2020-07-09 16:22:26)

I was just imagining we could get like an example like (NOT SURE IF THIS IS FORMATTED RIGHT AT ALL): echo 'db.settings.insert({_id: "preinstalledApps", value: {appId: "zx9d3pt0fjh4uqrprjftgpqfwgzp6y2ena6098ug3ctv37uv6kfh", status: "notReady", packageId: "128af0523f28d9e8ad195ca0927a4c73"}})' | sudo sandstorm mongo

That looks reasonable, though obviously it needs testing.

But as a meta-issue I feel like we shouldn't be to trigger-happy about telling the users to tweak the db manually, for a few reasons:

The "correct" response is to actually implement a relevant interface, not to tell people to muck around in the internals.

I think historically we've not done this because getting at the DB from the command line has been a little annoying. But that's kinda changed; see my earlier comment.

ocdtrekkie commented 4 years ago

I don't disagree with those points, though my main counter-thought is that I hesitate to ask someone to wait for us to develop the relevant interface, and then either: They move onto another solution prior to us implementing it, or we invested in implementing a solution that was only needed by one requestor, or in the case both are true: We spent time and effort developing a relevant interface that nobody at all used.

Which is to say, I feel like if @Fohroer found this useful, we could implement a better solution and then inform them of it when it's ready. But if we have the ability to help them do it now, I'd prefer to try to accomplish that.

That being said, I've always had a preference for monkeying around in the MySQL databases of PHP apps on my hosting... I've never considered manipulating the database directly to be a dark art I shouldn't do. (And, fair point, this has led me to often not write complete admin panels for my own apps out of laziness.)

zenhack commented 4 years ago

I'd be more comfy with it if we were using SQL, as the database itself can enforce integrity constraints. As far as mongo is concerned, the DB is just a bunch of misc. JSON blobs, so its' more likely a user could accidentally push it into some inconsistent state. The closest thing we have to a schema is the giant wall of comments in db.js.

I'm okay with an occasional "if you really need this now, you can do hack X" as long as we make it clear to folks that db corruption is possible if they do something wrong, there are no backwards compatibility guarantees, etc.

ocdtrekkie commented 4 years ago

That's fair. I kinda see the solutions we proposed here as enough for an MVP of the project being built here. If @Fohroer finds this useful we can then follow it up with better solutions.

FWIW, with the proposed install script file and database command, it'll either work or not work before any data is stored in a given Sandstorm install, so it should be pretty safe to experiment here.

Fohroer commented 4 years ago

This looks useful. I can give you some VDS for testing purposes. Can you perform test on VDSes? Which distro do you need and how many VDSes? Also please give me you public SSH keys.

ocdtrekkie commented 4 years ago

I mean, I can test on local VMs if I have time. Problem is I have limited time. If you are able to test these solutions and run into difficulties we may be able to help.

It's something I'd like to play with more, but I can't tell you how quickly I'd get to it.

I think the way to make Ian's file-with-responses strategy is to go through the install script and put what you type on each input query into a file on a new line. And then once you have that able to install Sandstorm successfully, you'd run the database command to add GitLab to the preinstalled apps list.

Fohroer commented 4 years ago

@ocdtrekkie OK, I'll try it by myself. Which distro do you recommend for tests?

ocdtrekkie commented 4 years ago

Ubuntu is probably the most common/best tested distro for Sandstorm, but most should work.

Fohroer commented 4 years ago

@ocdtrekkie AM I right that I need to run automatic install of Sandstorm, then run JS code for app install?

ocdtrekkie commented 4 years ago

Yeah, note that the app install command isn't JS code, it's something you'd also run from the shell, just after the install.

I would also point out this strategy (in addition to being untested) will fail if you run it using a Sandcats subdomain that is already taken, so for testing purposes, I'd use a Sandcats subdomain you don't actually want/care about until you know the strategy works.

zenhack commented 4 years ago

Just noticed looking at the command: the value is supposed to be a list, so you'll want an extra set of square brackets around it.

Fohroer commented 4 years ago

@ocdtrekkie Why this strategy will fail with Sandcats domain? Can I use another domain for automatic Sandstorm install and expect that system will work correctly? @zenhack So I need to perform curl request?

ocdtrekkie commented 4 years ago

@Fohroer This should work with Sandcats, it's just that if you use a Sandcats name that is already taken, this doesn't handle that. So if you try to run the script with example.sandcats.io in there, and then try to do it again, it'll fail the second time. You'll want to make sure you use a different sandcats subdomain each time.

What @zenhack means is that I think my command needs to be echo 'db.settings.insert({_id: "preinstalledApps", value: [{appId: "zx9d3pt0fjh4uqrprjftgpqfwgzp6y2ena6098ug3ctv37uv6kfh", status: "notReady", packageId: "128af0523f28d9e8ad195ca0927a4c73"}]})' | sudo sandstorm mongo because preinstalledApps is expecting a list. (Reminder: This command is still not tested, but I think I added the brackets where they would go?)

zenhack commented 4 years ago

Quoting Jacob Weisz (2020-07-14 15:03:21)

[1]@Fohroer This should work with Sandcats, it's just that if you use a Sandcats name that is already taken, this doesn't handle that. So if you try to run the script with example.sandcats.io in there, and then try to do it again, it'll fail the second time. You'll want to make sure you use a different sandcats subdomain each time.

Note that repeatedly grabbing new sandcats domains from the same IP is probably going to hit let's encrypt's rate limits sooner or later. It would be nice if we had a way to tell the installer to use the staging endpoint (maybe we should add one?)

I might advise doing the install part once, then backing up /opt/sandstorm and experiment by replacing /opt/sandstorm with the backup after each attempt. Once you've got that working you can script them to run in sequence.

[...]

but I think I added the brackets where they would go?

Almost; Should be value: [{...}] but you wrote value: {[...]} which would yield a syntax error.

ocdtrekkie commented 4 years ago

So many different brackets... I updated the comment above yours with that change.

Fohroer commented 4 years ago

This should work with Sandcats, it's just that if you use a Sandcats name that is already taken, this doesn't handle that. So if you try to run the script with example.sandcats.io in there, and then try to do it again, it'll fail the second time. You'll want to make sure you use a different sandcats subdomain each time. So I need to make a pre-check before order to make sure that name is not used at the moment? If someone deletes Sandstorm, when the name become fully free?

Note that repeatedly grabbing new sandcats domains from the same IP is probably going to hit let's encrypt's rate limits sooner or later. It would be nice if we had a way to tell the installer to use the staging endpoint (maybe we should add one?) AFAIK Let's Encrypt can give 5 certs to one IP per week. I don't think that there will be 5 reinstalls from one IP. Anyway, certbot supports dry run, so we can grep the result to make it a pre-check.

ocdtrekkie commented 4 years ago

I don't believe Sandcats ever releases old subdomains. Apparently some work was done back in the day on having some sort of "pre-registration" where you'd fill out a form and get a key for your Sandcats domain prior to trying to do a one-click install, but it was never finished.

Fohroer commented 4 years ago

This command is still not tested, but I think I added the brackets where they would go?)

Tried on fresh Ubuntu VM, installed Sandstorm manually, then logged in and tried your command. And here's the result:

root@ubuntu18:~# ufw disable
Firewall stopped and disabled on system startup
root@ubuntu18:~# echo 'db.settings.insert({_id: "preinstalledApps", value: [{appId: "zx9d3pt0fjh4uqrprjftgpqfwgzp6y2ena6098ug3ctv37uv6kfh", status: "notReady", packageId: "128af0523f28d9e8ad195ca0927a4c73"}]})' | sudo sandstorm mongo
MongoDB shell version: 2.6.7
connecting to: 127.0.0.1:6081/meteor
WriteResult({
    "nInserted" : 0,
    "writeError" : {
        "code" : 11000,
        "errmsg" : "insertDocument :: caused by :: 11000 E11000 duplicate key error index: meteor.settings.$_id_  dup key: { : \"preinstalledApps\" }"
    }
})
bye
root@ubuntu18:~# 

And that's all apps I can see: Apps

Fohroer commented 4 years ago

As I can see, this solution didn't install anything. I can give you access to VM if you need, just need your public SSH keys.

Fohroer commented 4 years ago

Hello!

Do you have any ideas about what to do to install app? Maybe we will try with another app?

ocdtrekkie commented 4 years ago

Hey, sorry. I know we're close, but my guess is 'insert' is the wrong command here since there are already some preinstalled apps. But I personally have done very little with Mongo.

zenhack commented 4 years ago

Yeah, you probably need to either remove the existing setting first, or use mongo's upsert command (which does an update or an insert depending on whether the value is already present). The first would be db.settings.remove({_id: "preinstalledApps"}).

Fohroer commented 4 years ago

@zenhack How to find values of the installed apps? Can I do it via browser developer console?

Here are my results:

root@ubuntu18:~# db.settings.remove({_id: "s3u2xgmqwznz2n3apf30sm3gw1d85y029enw5pymx734cnk5n78h"}) | sudo sandstorm mongo
-bash: syntax error near unexpected token `{_id:'

Am I right that we need to include new app to the list of preinstalled apps with such steps:

  1. Delete all standard apps from the list before they will be installed;
  2. Add new app to this list ?
ocdtrekkie commented 4 years ago

In the case above: You didn't "echo" the command into the Sandstorm mongo command, which is why you have a bash error. Also, you attempted to remove an appId, but the appId would be inside the preinstalledApps key. Perhaps try these two?

echo 'db.settings.remove({_id: "preinstalledApps"})' | sudo sandstorm mongo
echo 'db.settings.insert({_id: "preinstalledApps", value: [{appId: "zx9d3pt0fjh4uqrprjftgpqfwgzp6y2ena6098ug3ctv37uv6kfh", status: "notReady", packageId: "128af0523f28d9e8ad195ca0927a4c73"}]})' | sudo sandstorm mongo

Also, note that an existing user on Sandstorm will have the preinstalledApps from when the account was created. So if you're testing this on a Sandstorm server you've already gotten installed, you probably will need to create a different user account to see the amended behavior (if this works).

Fohroer commented 4 years ago

Perhaps try these two?

@ocdtrekkie I have tried this, then I saw GitLab in list of pre-installed apps from admin panel, have created new GitHub account for login purpose but no pre-installed apps appeared.

I also have tried from scratch on new server with another IP and take I look: it seems like I'm stuck on /setup/preinstalled with no ability to continue. I suppose that initial installer is kicking me off. No next

abliss commented 4 years ago

Can you click on the "system log" button at the bottom and let us know what it says?

Fohroer commented 4 years ago

@abliss Log is attached sandstorm.log

ocdtrekkie commented 4 years ago

Just looking at the setup wizard, it looks like it explicitly looks for the Productivity Suite apps and System Suite apps before continuing. :/

Presumably you could run those commands after the setup wizard is run, but your users are probably running that, so that wouldn't work experience-wise.

I'm not sure what triggers the setup wizard, but we probably need to basically implement a way to dump in enough settings that we don't need to run that at all? (see #3389)

ocdtrekkie commented 4 years ago

@Fohroer I think unfortunately this is going to get kind of messy. It looks like another setting called isPreinstalledAppsReady is checked to see if you can move beyond that step. Presumably, we could try to set that setting, but then I don't know if it would actually download GitLab. (As I am not super versed in where all of this is handled.)

It seems like the setup wizard is currently designed to assume the preinstalled apps are Sandstorm's Productivity and System Suites. And it would require code changes to fix that. It (might) be easier to add GitLab to one of those suites than try to replace them... However, we should open a separate issue for this, I think, as distributors might wish to use Sandstorm as the underlying platform for their own suites of apps.