Skip to content

Commit 7b68eeb

Browse files
committed
compute servers: massively improve the development instructions; document why allow_other is required for FUSE mounts
1 parent edefd44 commit 7b68eeb

File tree

6 files changed

+37
-14
lines changed

6 files changed

+37
-14
lines changed

src/compute/compute/dev/4-startup-script.sh

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,21 @@
1717

1818
set -v
1919

20-
export api_server=`cat conf/api_server`
21-
20+
. env.sh
2221

2322
function setState {
24-
id=`cat conf/compute_server_id`
23+
id=$COMPUTE_SERVER_ID
2524
name=$1
2625
state=${2:-'ready'}
2726
extra=${3:-''}
2827
timeout=${4:-0}
2928
progress=${5:-100}
29+
project_id=$PROJECT_ID
3030

3131
echo "$name is $state"
32-
curl -sk -u `cat conf/api_key`: -H 'Content-Type: application/json' -d "{\"id\":$id,\"name\":\"$name\",\"state\":\"$state\",\"extra\":\"$extra\",\"timeout\":$timeout,\"progress\":$progress}" $api_server/api/v2/compute/set-detailed-state
32+
PAYLOAD="{\"id\":$id,\"name\":\"$name\",\"state\":\"$state\",\"extra\":\"$extra\",\"timeout\":$timeout,\"progress\":$progress,\"project_id\":\"$project_id\"}"
33+
echo $PAYLOAD
34+
curl -sk -u $API_KEY: -H 'Content-Type: application/json' -d $PAYLOAD $API_SERVER/api/v2/compute/set-detailed-state
3335
}
3436

3537

src/compute/compute/dev/README.md

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,27 @@ This is potentially confusing, and when developing this it was 10x worse... Mayb
2323
4-startup-script.sh
2424
```
2525

26-
However, a bunch of things are likely to go wrong. The scripts `1-websocketfs.sh` and `2-syncfs.sh` will definitely fail if support for FUSE isn't enabled for normal users where you are working! Test bindfs locally. You probably have to add `user_allow_other` to `/etc/fuse.conf`. For `2-syncfs.sh`, you must also install unionfs-fuse via `sudo apt install unionfs-fuse` . Also, you need to do the following so that testing of tmp being a "fast local data directory that isn't sync"'d can be done:
26+
However, a bunch of things are likely to go wrong.
2727

28-
```
29-
~/cocalc/src/compute/compute/dev$ sudo mkdir /data/tmp
30-
~/cocalc/src/compute/compute/dev$ sudo chown `whoami`:`whoami` /data/tmp
28+
**Problem:** Regarding the id of the compute server in the file [conf/compute\_server\_id](./conf/compute_server_id), create a self\-hosted compute server in the project on your dev server, then find the record in the postgresql database by querying the `compute_servers` table, and copy the id field from that. Note that the displayed id in the UI starts from 1 for each project, but `compute_server_id` must be the id in the database.
29+
30+
**Problem:** Get the [conf/api_key](./conf/api_key) by clicking start on the self\-hosted compute server, inspect the URL, and copy it from there. If you stop the server explicitly, then the api key is deleted from the project, so you need to make it again.
31+
32+
**Problem:** The scripts `1-websocketfs.sh` and `2-syncfs.sh` will definitely fail if support for FUSE isn't enabled for normal users where you are working! Test bindfs locally.
33+
34+
**Problem:** For `2-syncfs.sh`, you must also install unionfs\-fuse via `sudo apt install unionfs-fuse,` since the cocalc package @cocalc/sync\-fs assumes unionfs\-fuse is installed.
35+
36+
**Problem:** You need to do the following so that you can fully test the scratch functionality \(see [conf/exclude_from_sync](./conf/exclude_from_sync)\):
37+
38+
```sh
39+
sudo mkdir -p /data/scratch && sudo chown -R `whoami`:`whoami` /data
3140
```
3241

33-
Once you get the 4 scripts above to run, the net result is basically the same as using a compute server, but you can run it all locally, and debugging is massively easier. Without something like this, development is impossible, and even figuring out what configuration goes where could cost me days of confusion (even though I wrote it all!). It's complicated.
42+
Once you get the 4 scripts above to run, the net result is basically the same as using a compute server, but you can run it all locally, and development and debugging is ~~massively easier~~ possible! Without something like this, development is impossible, and even figuring out what configuration goes where could cost me days of confusion \(even though I wrote it all!\). It's complicated.
3443

3544
For debugging set the DEBUG env variable to different things according to the debug npm module. E.g.,
3645

3746
```sh
38-
DEBUG=* 2-syncfs.sh
47+
DEBUG_CONSOLE=yes DEBUG=* ./2-syncfs.sh
3948
```
49+

src/compute/compute/dev/start-filesystem.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ async function main() {
4747
exports.fs = await mountProject({
4848
project_id: process.env.PROJECT_ID,
4949
path: PROJECT_HOME,
50-
options: { mountOptions: { allowOther: true, nonEmpty: true } },
50+
// NOTE: allowOther is disabled by default on Ubuntu and we do not need it.
51+
options: { mountOptions: { allowOther: false, nonEmpty: true } },
5152
unionfs,
5253
readTrackingFile: process.env.READ_TRACKING_FILE,
5354
exclude,

src/compute/compute/lib/filesystem.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,9 @@ export async function mountProject({
148148
...options.connectOptions,
149149
},
150150
mountOptions: {
151-
allowOther: true,
152-
nonEmpty: true,
153151
...options.mountOptions,
152+
allowOther: true, // this is critical to allow for fast bind mounts of scratch etc. as root.
153+
nonEmpty: true,
154154
},
155155
cacheTimeout,
156156
hidePath: "/.unionfs",
@@ -175,6 +175,11 @@ export async function mountProject({
175175
);
176176
websocketfsMountOptions.mountOptions.allowOther = false;
177177
({ unmount } = await mount(websocketfsMountOptions));
178+
179+
// This worked so the problem is allow_other.
180+
throw Error(
181+
"fusermount: option allow_other only allowed if 'user_allow_other' is set in /etc/fuse.conf\n\n\nFix this:\n\n sudo sed -i 's/#user_allow_other/user_allow_other/g' /etc/fuse.conf\n\n\n",
182+
);
178183
}
179184

180185
pingInterval = setInterval(async () => {

src/packages/server/compute/cloud/install.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,9 @@ systemctl restart docker
125125
`;
126126
}
127127

128+
// NOTE: we absolutely DO need "# Allow root to use FUSE mount of user" below.
129+
// This is needed so that we can do a very fast bind mount as root of fast
130+
// scratch directories on top of the slower fuse mounted home directory.
128131
export function installUser() {
129132
return `
130133
# Create the "user" if they do not already exist:
@@ -138,7 +141,7 @@ if ! id -u user >/dev/null 2>&1; then
138141
# Allow to be root
139142
echo '%user ALL=(ALL) NOPASSWD: ALL' >> /etc/sudoers
140143
141-
# Allow to use FUSE
144+
# Allow root to use FUSE mount of user
142145
sed -i 's/#user_allow_other/user_allow_other/g' /etc/fuse.conf
143146
144147
fi

src/packages/sync-fs/lib/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,8 @@ class SyncFS {
354354
};
355355

356356
private mountUnionFS = async () => {
357+
// NOTE: allow_other is essential to allow bind mounted as root
358+
// of fast scratch directories into HOME!
357359
// unionfs-fuse -o allow_other,auto_unmount,nonempty,large_read,cow,max_files=32768 /upper=RW:/home/user=RO /merged
358360
await execa("unionfs-fuse", [
359361
"-o",

0 commit comments

Comments
 (0)