@@ -0,0 +1,311 @@
1+# Obelisk Application Deployment Guide
2+This document serves two purposes, the first one is to guide new users that want to deploy Obelisk/Reflex apps and the second one to provide a walk-through for test driving Obelisk releases.
3+
4+> **Note:** To complete this *entire* guide you need access to a macOS machine running the latest OSX release, a Linux machine (can be a VM on that mac) with Nix installed, an iPhone or iPad, and a recent Android device. It also assumes that you have Nix correctly set up and that your system is set up to fetch from binary caches instead of building everything on your machine. If you notice any of the commands below takes more than 5 minutes, then caches are not likely enabled.
5+>
6+> Refer to the [Obelisk Installation Documentation](https://github.com/obsidiansystems/obelisk#installing-obelisk) for instructions on configuring the binary caches for any Nix-compatible setup.
7+
8+## a) Get Obelisk
9+
10+There are several ways to install Obelisk, but the one we are going to use here allows us to test a single version of Obelisk in different ways. The approach is to clone Obelisk from it's GitHub repository and start a project that uses that local check out.
11+
12+Open a terminal and run the following:
13+
14+```bash
15+export WORKDIR=~/obelisk-guide
16+mkdir -p "$WORKDIR"
17+```
18+
19+Then let's get Obelisk from GitHub using a specific branch:
20+
21+```bash
22+export OBELISK_BRANCH=develop
23+git clone https://github.com/obsidiansystems/obelisk.git -b "$OBELISK_BRANCH" "$WORKDIR/obelisk"
24+```
25+
26+Once you have an Obelisk check out, you can build it using Nix and make a shortcut (alias) for the rest of the terminal session. With this you will be able to type `ob` anywhere as long as you do not close the terminal.
27+
28+```bash
29+alias ob=$(nix-build "$WORKDIR/obelisk" -A command --no-out-link)/bin/ob
30+```
31+
32+In order to start an Obelisk project, we need initialize it in a new directory. Let's call it `myapp`:
33+
34+```bash
35+mkdir -p "$WORKDIR/myapp"
36+cd "$WORKDIR/myapp"
37+ob init --branch "$OBELISK_BRANCH"
38+```
39+
40+> **Note:** If the `--branch` parameter is not used, then Obelisk sets your project up to look at the `master` branch from GitHub. This is quite handy for real life projects but distracting for our test drive since we want to make sure any changes we do to the Obelisk codebase (like testing a pull request) are immediately picked up.
41+
42+## b) Run the Obelisk app on localhost
43+
44+Let's test that we can run a server on localhost. This is quite easy:
45+
46+```bash
47+cd "$WORKDIR/myapp"
48+ob run
49+```
50+
51+Now open a browser and point it to http://localhost:8000 (or just click on this link). You should see the following:
52+
53+
54+
55+## c) Deploy the web app on a remote machine
56+
57+### Import the NixOS VirtualBox appliance
58+Install [VirtualBox](https://www.virtualbox.org/) on your machine.
59+
60+On NixOS, do this by adding the following line to your `/etc/nixos/configuration.nix` before the last line containing `}`:
61+
62+```nix
63+ virtualisation.virtualbox.host.enable = true;
64+```
65+
66+then `sudo nixos-rebuild switch`.
67+
68+The NixOS [download page](https://nixos.org/nixos/download.html) has a section called "VirtualBox appliances". Download that as the target system. The author used the 19.09 `.ova` file.
69+
70+With the downloaded file, open VirtualBox and import the `.ova` file:
71+
72+
73+
74+Leave the default settings and finish the import. That will take a few minutes:
75+
76+
77+
78+You should now see a NixOS machine in the dashboard:
79+
80+
81+
82+If you are on a network with DHCP on your wireless or network card then select right-click on the "NixOS" image and click "Settings". Go to the "Network" section and make "Attached to:" set to "Bridged Adapter".
83+
84+
85+
86+Finally, double-click on the "NixOS" machine and wait for it boot up. If it asks for a password, use `demo`.
87+
88+
89+
90+### Configure the virtual machine for SSH
91+
92+Inside the virtual machine open up "Konsole" by clicking on the start menu in the bottom left corner and typing in "Konsole" until you see it as an option in the menu. Then click on it to open it.
93+
94+Change the system configuration using `sudo` to enable SSH access:
95+
96+```bash
97+sudo nano /etc/nixos/configuration.nix
98+```
99+
100+This will ask you to enter your password. Enter `demo`.
101+
102+
103+
104+You need to add the following snippet right before the final line containing `}`.
105+
106+```nix
107+ services.openssh.enable = true;
108+ services.openssh.permitRootLogin = "yes";
109+```
110+
111+Save and close the editor by typing <kbd>Ctrl</kbd>+<kbd>O</kbd>, <kbd>Enter</kbd>, and then <kbd>Ctrl</kbd>+<kbd>X</kbd>.
112+
113+Now run `sudo nixos-rebuild switch` (if it asks for a password, again use `demo`) and then set the root password using `sudo passwd root`. Pick a simple password like `root`. You'll need to use it again.
114+
115+To get the virtual machine's IP address go back to the terminal on your *host* machine (not the virtual machine) and run:
116+
117+```bash
118+export VM_ID=$(VBoxManage list runningvms | grep "NixOS" | awk -F'[{}]' '{print $2}')
119+echo "$VM_ID"
120+```
121+
122+You should see a single identifier that looks like `388bbbe5-e0a2-4b20-9c76-bbaa5746682e`. If you see anything else then you likely you have multiple NixOS machines running. Stop any other machines and run this command again. (Of course, if you're a power user, just change the `grep` to pick out right VM.)
123+
124+Now get the IP address for that machine:
125+
126+```bash
127+export VM_IP=$(VBoxManage guestproperty enumerate "$VM_ID" | grep /V4/IP | awk '{print $4}' | sed 's/,//')
128+echo "$VM_IP"
129+```
130+
131+You should see an IP like `192.168.7.86`.
132+
133+With that you will be able to SSH into that machine from a terminal, using the username `root`.
134+
135+```bash
136+ssh root@$VM_IP echo "Access granted"
137+```
138+
139+This may ask if you want to trust the fingerprint for this server. Answer `yes`. It will ask you for a password. Enter the one you specified above. You should see `Access granted` printed after you type your password and hit <kbd>Enter</kbd>.
140+
141+> **Note:** If instead you see an error like this
142+>
143+> ```
144+> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
145+> @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
146+> @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
147+> IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
148+> Someone could be eavesdropping on you right now (man-in-the-middle attack)!
149+> It is also possible that a host key has just been changed.
150+> ```
151+>
152+> you need to remove the old fingerprint for this IP. Run the following:
153+>
154+> ```bash
155+> sed -i "/^$VM_IP /d" ~/.ssh/known_hosts
156+> ```
157+>
158+> and then try the previous `ssh` command again.
159+
160+Now we'll allow access with an SSH key instead of a password. Create a new SSH key with `ssh-keygen`:
161+
162+```bash
163+ssh-keygen -t ed25519 -f "$WORKDIR/obkey" -P ""
164+```
165+
166+Now copy your local SSH key to the server:
167+
168+```bash
169+ssh-copy-id -i "$WORKDIR/obkey.pub" root@$VM_IP
170+```
171+
172+This will ask you for your password again.
173+
174+Now test login with your key instead:
175+
176+```bash
177+ssh -i "$WORKDIR/obkey" root@$VM_IP echo "Access granted"
178+```
179+
180+This should print `Access granted` *without* asking for a password.
181+
182+### Configure the git remote
183+
184+Before the project can be deployed, it needs to be a valid `git` repository.
185+
186+> **Note:** You need `git` installed and configured. You can do that with:
187+>
188+> ```bash
189+> nix-env -i git
190+> git config --global user.name "John Doe"
191+> git config --global user.email johndoe@example.com
192+> ```
193+
194+```bash
195+git init --bare "$WORKDIR/myapp-git-remote"
196+cd "$WORKDIR/myapp"
197+git init
198+git add --all
199+git commit -m "initial commit"
200+git remote add origin "$WORKDIR/myapp-git-remote"
201+git push -u origin master
202+```
203+
204+### Deploy
205+
206+With that, we can come back to the Obelisk app and initialize the deployment:
207+
208+```bash
209+cd "$WORKDIR/myapp"
210+ob deploy init --ssh-key "$WORKDIR/obkey" --admin-email a@a.a --hostname $VM_IP --route https://$VM_IP "$WORKDIR/myappdeploy" --disable-https
211+```
212+
213+Then configure the deployment for VirtualBox:
214+
215+```bash
216+echo '{nixosPkgs, ...}: {...}: { imports = [ (nixosPkgs.path + /nixos/modules/virtualisation/virtualbox-image.nix) ]; }' > "$WORKDIR/myappdeploy/module.nix"
217+```
218+
219+And deploy:
220+
221+```bash
222+cd "$WORKDIR/myappdeploy"
223+ob deploy push -v
224+```
225+
226+Once that is complete, open the webpage with
227+
228+```bash
229+xdg-open http://$VM_IP
230+```
231+
232+If that fails, just get the URL by running
233+
234+```bash
235+echo http://$VM_IP`
236+```
237+
238+and copy/paste that URL into your browser navigation input.
239+
240+It should look like this:
241+
242+
243+
244+Congratulations! You have deployed an Obelisk application to a remote server via SSH.
245+
246+## d) Deploy an Android app (Linux host only)
247+
248+> **Note:** This section requires that you be running a Linux *host*.
249+
250+Modify `$WORKDIR/myapp/default.nix` to set `config.android_sdk.accept_license = true;` and then update your app.
251+
252+```bash
253+cd "$WORKDIR/myapp"
254+sed -i 's/# config.android_sdk.accept_license = false;/config.android_sdk.accept_license = true;/g' default.nix
255+git add default.nix
256+git commit -m"Accept license"
257+git push
258+```
259+
260+Make sure *USB debugging* is enabled in your Android device ([instructions here](https://developer.android.com/studio/debug/dev-options) and connect the device using USB. Be sure to confirm any security prompts on the device.
261+
262+Now update your deployment and deploy to Android:
263+
264+```bash
265+cd "$WORKDIR/myappdeploy"
266+ob deploy update
267+ob deploy test android -v
268+```
269+
270+This deployment will ask you to create a password (at least 6 characters long) and then ask you a series of questions. You can pick arbitrary answers. If the deployment fails, try using different USB ports on your computer and running `ob deploy test android -v` again. The USB cable you use can also make a difference.
271+
272+When connecting your Android device you may be asked to "Allow USB debugging". You need to allow it.
273+
274+
275+
276+When the deployment is complete opening the app should look something like
277+
278+
279+
280+Congratulations! You have deployed an Obelisk Android app via USB.
281+
282+## e) Deploy an iOS app (macOS host only)
283+
284+> **Note:** This section requires that you be running a macOS *host*.
285+
286+Verify that you can see the device from XCode and you have installed a Provisioning profile that links your Apple Developer Id and the Device identifier. The workflow depends on whether or not you are an independent developer or part of an organization and is out of scope for this manual.
287+
288+
289+
290+Find your `Team ID` at the following URL (Apple Developer Membership details): https://developer.apple.com/account/#/membership/
291+
292+It will be something like `5B445B3WY1`. With that, you can start the deployment workflow after plugging in an iPhone or iPad via USB and setting it to trust the computer:
293+
294+```bash
295+cd "$WORKDIR/myappdeploy"
296+ob deploy test ios <TEAM-ID> # Use your Team ID here
297+```
298+
299+
300+
301+
302+
303+If there are no errors and the last line says `100% Installed Package` you can open the device and look for the Obelisk app:
304+
305+
306+
307+
308+
309+Congratulations, you have deployed an Obelisk app on an iOS device.
310+
311+You are now ready to create your own multi-platform application using Obelisk!