@twin.org/node 0.0.3-next.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,223 @@
1
+ # @twin.org/node - Configuration
2
+
3
+ ## Extension Loading
4
+
5
+ The TWIN Node supports loading extensions dynamically to extend its functionality. Extensions can be loaded from multiple sources using protocol-based syntax.
6
+
7
+ ### Extension Loading Syntax
8
+
9
+ Extensions are configured via the `TWIN_EXTENSIONS` environment variable. Multiple extensions can be specified as a comma-separated list.
10
+
11
+ #### Local File Extensions
12
+
13
+ Load extensions from the local filesystem:
14
+
15
+ ```bash
16
+ # Relative path
17
+ TWIN_EXTENSIONS="./my-extension.mjs"
18
+
19
+ # Absolute path
20
+ TWIN_EXTENSIONS="/path/to/extension.mjs"
21
+ ```
22
+
23
+ #### NPM Package Extensions
24
+
25
+ Load extensions from npm packages. The package will be automatically downloaded and installed if not already cached:
26
+
27
+ ```bash
28
+ # Basic npm package
29
+ TWIN_EXTENSIONS="npm:@twin.org/identity-management-service"
30
+
31
+ # Scoped package
32
+ TWIN_EXTENSIONS="npm:@org/custom-extension"
33
+ ```
34
+
35
+ **Note:** Version pinning (e.g., `npm:@twin.org/pkg@1.2.3`) is planned for a future release. Currently, the latest version is installed.
36
+
37
+ #### HTTPS URL Extensions
38
+
39
+ Load extensions from remote HTTPS URLs:
40
+
41
+ ```bash
42
+ TWIN_EXTENSIONS="https://example.twin.org/extensions/my-module.mjs"
43
+ ```
44
+
45
+ **⚠️ SECURITY WARNING:** Loading code from HTTPS URLs introduces security risks. Only load extensions from trusted sources that you control or verify.
46
+
47
+ Security features:
48
+
49
+ - Only HTTPS is allowed (HTTP is rejected)
50
+ - Default 10 MB size limit to prevent DoS attacks
51
+ - Downloaded modules are cached locally
52
+ - Security warning is displayed when loading
53
+
54
+ #### Multiple Extensions
55
+
56
+ Load multiple extensions from different sources:
57
+
58
+ ```bash
59
+ TWIN_EXTENSIONS="@twin.org/identity-management-service,npm:@twin.org/custom-service,./local-extension.mjs,https://example.com/remote.mjs"
60
+ ```
61
+
62
+ ### Extension Configuration Options
63
+
64
+ #### Maximum Download Size
65
+
66
+ Configure the maximum size (in MB) for HTTPS extension downloads:
67
+
68
+ ```bash
69
+ TWIN_EXTENSIONS_MAX_SIZE_MB=10 # Default is 10 MB
70
+ ```
71
+
72
+ #### Cache Management
73
+
74
+ By default, downloaded extensions are cached in `.tmp/extensions/` directory to speed up subsequent startups. To clear the cache on each startup:
75
+
76
+ ```bash
77
+ TWIN_EXTENSIONS_CLEAR_CACHE=true # Default is false
78
+ ```
79
+
80
+ #### Custom Cache Directory
81
+
82
+ You can configure a custom directory for extension caching:
83
+
84
+ ```bash
85
+ TWIN_EXTENSIONS_CACHE_DIRECTORY="cache" # Default is ".tmp"
86
+ ```
87
+
88
+ This allows you to:
89
+
90
+ - Use a dedicated partition with more space
91
+ - Separate cache by environment (dev/staging/prod)
92
+ - Follow corporate storage policies
93
+ - Create persistent cache directories for better performance
94
+
95
+ ### Extension API
96
+
97
+ Extensions must export specific lifecycle methods to integrate with the node:
98
+
99
+ #### `extensionInitialise(envVars, nodeEngineConfig)`
100
+
101
+ Called during configuration phase. Allows the extension to modify environment variables and engine configuration.
102
+
103
+ ```typescript
104
+ export async function extensionInitialise(
105
+ envVars: INodeEnvironmentVariables,
106
+ nodeEngineConfig: INodeEngineConfig
107
+ ): Promise<void> {
108
+ // Modify configuration here
109
+ }
110
+ ```
111
+
112
+ #### `extensionInitialiseEngine(engineCore)`
113
+
114
+ Called after the engine is created but before the server starts.
115
+
116
+ ```typescript
117
+ export async function extensionInitialiseEngine(engineCore: IEngineCore): Promise<void> {
118
+ // Register components, set up services, etc.
119
+ }
120
+ ```
121
+
122
+ #### `extensionInitialiseEngineServer(engineCore, engineServer)`
123
+
124
+ Called after the engine server is created but before it starts listening.
125
+
126
+ ```typescript
127
+ export async function extensionInitialiseEngineServer(
128
+ engineCore: IEngineCore,
129
+ engineServer: IEngineServer
130
+ ): Promise<void> {
131
+ // Add routes, configure server, etc.
132
+ }
133
+ ```
134
+
135
+ #### `extensionShutdown()`
136
+
137
+ Called when the node is shutting down. Clean up resources here.
138
+
139
+ ```typescript
140
+ export async function extensionShutdown(): Promise<void> {
141
+ // Clean up resources
142
+ }
143
+ ```
144
+
145
+ ### Example Extension
146
+
147
+ ```typescript
148
+ // my-extension.mjs
149
+ export async function extensionInitialise(envVars, nodeEngineConfig) {
150
+ console.log('Extension initializing with config');
151
+ }
152
+
153
+ export async function extensionInitialiseEngine(engineCore) {
154
+ engineCore.logInfo('Custom extension loaded');
155
+ }
156
+
157
+ export async function extensionInitialiseEngineServer(engineCore, engineServer) {
158
+ // Add custom routes
159
+ engineServer.addRestRoute({
160
+ path: '/custom/endpoint',
161
+ method: 'GET',
162
+ handler: async () => ({ body: { message: 'Hello from extension!' } })
163
+ });
164
+ }
165
+
166
+ export async function extensionShutdown() {
167
+ console.log('Extension shutting down');
168
+ }
169
+ ```
170
+
171
+ ### Cache Directory Structure
172
+
173
+ Downloaded extensions are stored in:
174
+
175
+ ```text
176
+ <execution-directory>/<cache-directory>/extensions/
177
+ ├── npm/ # NPM packages
178
+ │ └── node_modules/
179
+ │ └── @twin.org/...
180
+ └── https/ # HTTPS downloads
181
+ └── <hashed-filename>.mjs
182
+ ```
183
+
184
+ Where `<cache-directory>` is:
185
+
186
+ - `.tmp` by default
187
+ - Configurable via `TWIN_EXTENSIONS_CACHE_DIRECTORY`
188
+
189
+ Examples:
190
+
191
+ - Default: `./.tmp/extensions/`
192
+ - Custom: `./cache/extensions/` (if `TWIN_EXTENSIONS_CACHE_DIRECTORY="cache"`)
193
+ - Absolute: `/var/cache/twin-node/extensions/` (if `TWIN_EXTENSIONS_CACHE_DIRECTORY="/var/cache/twin-node"`)
194
+
195
+ ### Security Best Practices
196
+
197
+ 1. **Prefer npm: protocol** over https: for third-party extensions (npm has package verification and malware scanning)
198
+ 2. **Use local files** (`./extension.mjs`) for maximum security and control
199
+ 3. **Verify HTTPS sources** before using - only load from domains you trust
200
+ 4. **Review extension code** before deployment, especially for HTTPS sources
201
+ 5. **Monitor cache directory** - review what's been downloaded to `.tmp/extensions/`
202
+ 6. **Use environment-specific configuration** - different extensions for dev/staging/prod
203
+
204
+ ### Troubleshooting
205
+
206
+ #### Extension fails to load
207
+
208
+ - Check that npm is installed and accessible in PATH (required for npm: protocol)
209
+ - Verify the extension file/URL is accessible
210
+ - Check `.tmp/extensions/` cache for partially downloaded files
211
+ - Review node logs for specific error messages
212
+
213
+ #### Clear extension cache manually
214
+
215
+ ```bash
216
+ rm -rf .tmp/extensions
217
+ ```
218
+
219
+ #### NPM package not found
220
+
221
+ - Verify the package name is correct
222
+ - Check network connectivity
223
+ - Ensure npm registry is accessible
@@ -0,0 +1,189 @@
1
+ # @twin.org/node - Deployment Docker
2
+
3
+ ## Docker Building
4
+
5
+ To run the API server in the docker environment there is an example dockerfile in `deploy/dockerfile`:
6
+
7
+ ```shell
8
+ # Set the base image
9
+ FROM node:22
10
+
11
+ # Create the app directory
12
+ WORKDIR /app
13
+
14
+ # Copy the package.json
15
+ COPY package.json .
16
+
17
+ # Install dependencies including dev dependencies needed for merge-locales
18
+ RUN npm install --ignore-scripts
19
+
20
+ # Copy the rest of the files to the image
21
+ COPY . .
22
+
23
+ # Compile translation messages
24
+ RUN npm run merge-locales
25
+
26
+ # Remove dev dependencies to reduce image size
27
+ RUN npm prune --omit=dev
28
+
29
+ # Expose the port the app runs on
30
+ EXPOSE 3000
31
+
32
+ # Set the environment variables that will override the .env file in the package
33
+ ENV TWIN_HOST=0.0.0.0
34
+ ENV TWIN_PORT=3000
35
+ ENV TWIN_STORAGE_FILE_ROOT=/twin-node/data
36
+
37
+ # Start the server
38
+ CMD ["node", "src/index.mjs"]
39
+ ```
40
+
41
+ You can build and execute this using docker from the root of the package with the following command.
42
+
43
+ ```shell
44
+ docker build -t twin-node -f deploy/dockerfile . --load
45
+ ```
46
+
47
+ > **Note**: The `--load` flag is required when using Docker Buildx to ensure the image is loaded into your local Docker registry. Without it, the image will only exist in the build cache.
48
+
49
+ This will build and deploy an image called `twin-node` to your local docker server.
50
+
51
+ ## Bootstrapping
52
+
53
+ Whenever the server starts it bootstraps all the components. If you have any entity storage configured to use `file` storage you should map a directory on the local host to contain the data, so that it remains persistent.
54
+
55
+ ```shell
56
+ docker run -t -i -v /home/twin-node/data:/twin-node/data -p 3000:3000 twin-node
57
+ ```
58
+
59
+ This example will map the local directory `/home/twin-node/data` and make it available in the docker container as `/twin-node/data` which is used to configure file entity storage using the environment variable `TWIN_STORAGE_FILE_ROOT`.
60
+
61
+ The output from the docker container should be something like the following.
62
+
63
+ ```shell
64
+ 🌩️ TWIN Node Server v1.0.0
65
+
66
+ Execution Directory: /app
67
+ Locales Directory: /app/dist/locales
68
+ Locales File: /app/dist/locales/en.json
69
+ OpenAPI Spec File: /app/docs/open-api/spec.json
70
+ Favicon File: /app/static/favicon.ico
71
+ Environment Variable Prefix: TWIN_
72
+ Default Environment File: /app/.env
73
+
74
+ INFO [2025-10-03T01:23:42.634Z] EngineCore Engine is starting
75
+ INFO [2025-10-03T01:23:42.635Z] EngineCore Debugging is enabled
76
+ INFO [2025-10-03T01:23:42.636Z] EngineCore Loading state from file storage with filename "twin-node/data/engine-state.json"
77
+ INFO [2025-10-03T01:23:42.637Z] EngineCore Configuring loggingConnector: console
78
+ INFO [2025-10-03T01:23:42.637Z] EngineCore Configuring loggingConnector: entity-storage
79
+ INFO [2025-10-03T01:23:42.638Z] EngineCore Configuring Entity Storage with name "log-entry" using "file" connector
80
+ INFO [2025-10-03T01:23:42.638Z] EngineCore Configuring loggingConnector: multi
81
+ INFO [2025-10-03T01:23:42.638Z] EngineCore Configuring loggingComponent: service
82
+ ...
83
+ INFO [2025-10-03T01:23:42.655Z] EngineCore Bootstrap started
84
+ ...
85
+ INFO [2025-10-03T01:23:42.662Z] EngineCore Generating mnemonic "weird focus prevent jewel enemy reveal supply dove then swallow topple goose case over endless garage width panic learn ask close fault immune shadow"
86
+ INFO [2025-10-03T01:23:42.662Z] EngineCore Storing mnemonic
87
+ INFO [2025-10-03T01:23:43.912Z] EngineCore Funding wallet "https://explorer.iota.org/address/0x69d531810657960fa07d346cb9bb7003e016e38c0b7486607002a10990ea0dd9?network=testnet"
88
+ INFO [2025-10-03T01:23:46.547Z] EngineCore Generating node identity
89
+ INFO [2025-10-03T01:23:49.584Z] EngineCore Node identity created "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82"
90
+ INFO [2025-10-03T01:23:49.585Z] EngineCore Identity explorer "https://explorer.iota.org/object/0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82?network=testnet"
91
+ INFO [2025-10-03T01:23:49.595Z] EngineCore Node identity "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82"
92
+ INFO [2025-10-03T01:23:49.596Z] EngineCore Creating node user "admin@node"
93
+ INFO [2025-10-03T01:23:49.597Z] EngineCore Node Admin User Email "admin@node"
94
+ INFO [2025-10-03T01:23:49.597Z] EngineCore Node Admin User Password "ayc^YC31TF%BVshQ"
95
+ INFO [2025-10-03T01:23:49.600Z] EngineCore Creating user profile "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82"
96
+ INFO [2025-10-03T01:23:49.601Z] EngineCore Creating authentication key "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82/auth-signing"
97
+ INFO [2025-10-03T01:23:49.617Z] EngineCore Creating blob encryption key "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82/blob-encryption"
98
+ INFO [2025-10-03T01:23:49.624Z] EngineCore Created blob encryption key "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82/blob-encryption" with value "4+S7bupEk/vLVhGxjKJ3jWw3uKo+3JsF8wYoB5B59bc="
99
+ INFO [2025-10-03T01:23:50.314Z] EngineCore Adding attestation verification method "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82#attestation-assertion"
100
+ INFO [2025-10-03T01:23:56.408Z] EngineCore Adding immutable proof verification method "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82#immutable-proof-assertion"
101
+ INFO [2025-10-03T01:24:01.772Z] EngineCore Bootstrap complete
102
+ INFO [2025-10-03T01:24:01.773Z] EngineCore Components are starting
103
+ ...
104
+ INFO [2025-10-03T01:24:02.476Z] EngineCore Components have started
105
+ INFO [2025-10-03T01:24:02.476Z] EngineCore Engine has started
106
+ INFO [2025-10-03T01:24:02.477Z] EngineCore Saving state to file storage with filename "twin-node/data/engine-state.json"
107
+ INFO [2025-10-03T01:24:02.496Z] FastifyWebServer Building Web Server
108
+ ...
109
+ INFO [2025-10-03T01:24:03.111Z] FastifyWebServer Starting Web Server at address "0.0.0.0" on port "3000"
110
+ INFO [2025-10-03T01:24:03.128Z] FastifyWebServer The Web Server started on http://0.0.0.0:3000
111
+ ```
112
+
113
+ You will see it generated a node admin user with password for future use, these should be recorded as they will not be made visible again.
114
+
115
+ To run the bootstrap again you would have to manually remove the `engine-state.json` from the data directory.
116
+
117
+ ## Docker Running
118
+
119
+ To run the server we use exactly the same command as before, when the `engine-state.json` exists the component states are passed in to the components.
120
+
121
+ ```shell
122
+ docker run -t -i -v /home/twin-node/data:/twin-node/data -p 3000:3000 twin-node
123
+ ```
124
+
125
+ You should now see output similar to the following:
126
+
127
+ ```shell
128
+ 🌩️ TWIN Node Server v1.0.0
129
+
130
+ Execution Directory: /app
131
+ Locales Directory: /app/dist/locales
132
+ Locales File: /app/dist/locales/en.json
133
+ OpenAPI Spec File: /app/docs/open-api/spec.json
134
+ Favicon File: /app/static/favicon.ico
135
+ Environment Variable Prefix: TWIN_
136
+ Default Environment File: /app/.env
137
+
138
+ INFO [2025-10-03T01:23:42.634Z] EngineCore Engine is starting
139
+ INFO [2025-10-03T01:23:42.635Z] EngineCore Debugging is enabled
140
+ INFO [2025-10-03T01:23:42.636Z] EngineCore Loading state from file storage with filename "twin-node/data/engine-state.json"
141
+ INFO [2025-10-03T01:23:42.637Z] EngineCore Configuring loggingConnector: console
142
+ INFO [2025-10-03T01:23:42.637Z] EngineCore Configuring loggingConnector: entity-storage
143
+ INFO [2025-10-03T01:23:42.638Z] EngineCore Configuring Entity Storage with name "log-entry" using "file" connector
144
+ INFO [2025-10-03T01:23:42.638Z] EngineCore Configuring loggingConnector: multi
145
+ INFO [2025-10-03T01:23:42.638Z] EngineCore Configuring loggingComponent: service
146
+ ...
147
+ INFO [2025-10-03T01:23:42.655Z] EngineCore Bootstrap started
148
+ ...
149
+ INFO [2025-10-03T01:27:34.331Z] EngineCore Wallet already funded
150
+ INFO [2025-10-03T01:27:35.064Z] EngineCore Node identity already exists "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82"
151
+ INFO [2025-10-03T01:27:35.065Z] EngineCore Identity explorer "https://explorer.iota.org/object/0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82?network=testnet"
152
+ INFO [2025-10-03T01:27:35.065Z] EngineCore Node identity "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82"
153
+ INFO [2025-10-03T01:27:35.066Z] EngineCore Node user already exists "admin@node"
154
+ INFO [2025-10-03T01:27:35.066Z] EngineCore User profile already exists "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82"
155
+ INFO [2025-10-03T01:27:35.067Z] EngineCore Authentication key already exists "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82/auth-signing"
156
+ INFO [2025-10-03T01:27:35.067Z] EngineCore Blob encryption key already exists "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82/blob-encryption"
157
+ INFO [2025-10-03T01:27:35.807Z] EngineCore Verification method for attestation already exists "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82#attestation-assertion"
158
+ INFO [2025-10-03T01:27:36.512Z] EngineCore Verification method for immutable proof already exists "did:iota:testnet:0xc7aa88cd54c8c90fc1cbe5927b3e2fe33d478ca7b6b058020c0d87e8f88fac82#immutable-proof-assertion"
159
+ INFO [2025-10-03T01:27:36.512Z] EngineCore Bootstrap complete
160
+ INFO [2025-10-03T01:24:01.773Z] EngineCore Components are starting
161
+ ...
162
+ INFO [2025-10-03T01:24:02.476Z] EngineCore Components have started
163
+ INFO [2025-10-03T01:24:02.476Z] EngineCore Engine has started
164
+ INFO [2025-10-03T01:24:02.477Z] EngineCore Saving state to file storage with filename "twin-node/data/engine-state.json"
165
+ INFO [2025-10-03T01:24:02.496Z] FastifyWebServer Building Web Server
166
+ ...
167
+ INFO [2025-10-03T01:24:03.111Z] FastifyWebServer Starting Web Server at address "0.0.0.0" on port "3000"
168
+ INFO [2025-10-03T01:24:03.128Z] FastifyWebServer The Web Server started on http://0.0.0.0:3000
169
+ ```
170
+
171
+ You should now be able to access the server in the browser [http://localhost:3000/info](http://localhost:3000/info).
172
+
173
+ On successfully communicating with the server you should see something similar to the following returned from the request:
174
+
175
+ ```json
176
+ {
177
+ "name": "TWIN Node Server",
178
+ "version": "1.0.0"
179
+ }
180
+ ```
181
+
182
+ The logging in the docker container should also show the request and response.
183
+
184
+ ```shell
185
+ INFO [2024-07-24T08:46:25.283Z] ===> GET /info
186
+ INFO [2024-07-24T08:46:25.287Z] <=== 200 GET /info duration: 3987µs {"name":"TWIN Node Server","version":"1.0.0"}
187
+ ```
188
+
189
+ The API server responds to the correct terminate signals so that when the docker container is stopped the server will also stop gracefully.
@@ -0,0 +1,193 @@
1
+ # @twin.org/node - Deployment Amazon AWS EC2
2
+
3
+ ## Amazon AWS EC2 Instance
4
+
5
+ To run the server on an AWS EC2 instance follow the steps below:
6
+
7
+ First follow one of the many online guides to create your EC2 instance with the ability to connect to it in terminal mode.
8
+
9
+ Network requirements are for the `https` port to be open to any address range i.e. `0.0.0.0`.
10
+
11
+ You should alias a domain name to the IP address of the instance e.g. `twin-node-api.example.com` using your DNS provider e.g. Cloudflare.
12
+
13
+ ## Install Git
14
+
15
+ For retrieving the code from the repo.
16
+
17
+ ```shell
18
+ sudo yum install git -y
19
+ git -version
20
+ ```
21
+
22
+ ## Install NVM and Node
23
+
24
+ For building and running the application.
25
+
26
+ ```shell
27
+ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
28
+ nvm install 20
29
+ node -v
30
+ ```
31
+
32
+ ## Install nginx
33
+
34
+ To serve the app through an https reverse proxy.
35
+
36
+ ```shell
37
+ sudo yum install nginx -y
38
+ nginx -v
39
+ ```
40
+
41
+ ## Configuring nginx
42
+
43
+ We need to configure nginx to use the certificate and reverse proxy https traffic to the node server.
44
+
45
+ ```shell
46
+ sudo nano /etc/nginx/nginx.conf
47
+ ```
48
+
49
+ The configuration should be along the lines of:
50
+
51
+ ```shell
52
+ server {
53
+ listen 80;
54
+ server_name twin-node-api.example.com;
55
+
56
+ # Redirect all traffic
57
+ return 301 https://$server_name$request_uri;
58
+ }
59
+
60
+ server {
61
+ listen [::]:443 ssl ipv6only=on;
62
+ listen 443 ssl;
63
+
64
+ server_name twin-node-api.example.com;
65
+
66
+ ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
67
+ ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
68
+
69
+ location / {
70
+ # Redirect the https traffic to the node instance
71
+ proxy_pass http://localhost:3000;
72
+ proxy_set_header Host $host;
73
+ proxy_set_header X-Real-IP $remote_addr;
74
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
75
+ proxy_set_header X-Forwarded-Proto $scheme;
76
+ }
77
+
78
+ location /socket {
79
+ # Redirect the wss traffic to the node instance
80
+ proxy_pass http://localhost:3000;
81
+ proxy_set_header Host $host;
82
+ proxy_set_header Upgrade $http_upgrade;
83
+ proxy_set_header Connection "upgrade";
84
+ }
85
+ }
86
+ ```
87
+
88
+ Once configured you can restart nginx with `sudo systemctl restart nginx`
89
+
90
+ Run `sudo systemctl enable nginx` to auto start the server on instance startup.
91
+
92
+ ## Building the server
93
+
94
+ We clone the repo, build it and then make a copy of the relevant .env file.
95
+
96
+ ```shell
97
+ git clone https://github.com/twinfoundation/node.git
98
+ cd apps
99
+ npm install
100
+ npm run dist
101
+ cd apps/node
102
+ cp .env.example-entity-storage .env
103
+ ```
104
+
105
+ The .env file can be modified to suit your own use case. For example to set the location for the storage.
106
+
107
+ ```shell
108
+ TWIN_STORAGE_FILE_ROOT="/home/ec2-user/twin-node/"
109
+ ```
110
+
111
+ ## Bootstrapping the server
112
+
113
+ You can now bootstrap the server, this will initialise all the required services and generate an initial configuration file. You should take note of the information in the logging as it will display information such as node admin passwords which will only be displayed once.
114
+
115
+ ```shell
116
+ node ./dist/es/index.js
117
+ ```
118
+
119
+ You should also now be able to access the server at `https://twin-node-api.example.com`
120
+
121
+ ## Configure the server to restart with server
122
+
123
+ We now need to install the server as a service, so that after any reboot it will continue to run.
124
+
125
+ Stop the server with `Ctrl-C`.
126
+
127
+ Create a service file e.g. `twin-node.service`
128
+
129
+ You might need to modify the location for the node version, you can find this out using `whereis node`
130
+
131
+ ```shell
132
+ [Unit]
133
+ Description=TWIN Node Server
134
+ After=network.target
135
+
136
+ [Service]
137
+ ExecStart=/home/ec2-user/.nvm/versions/node/v20.16.0/bin/node /home/ec2-user/twin-node/apps/twin-node/dist/es/index.js
138
+ Restart=always
139
+ User=ec2-user
140
+ Group=ec2-user
141
+ Environment=PATH=/usr/bin:/usr/local/bin
142
+ Environment=NODE_ENV=production
143
+ WorkingDirectory=/home/ec2-user/twin-node/apps/twin-node/
144
+
145
+ [Install]
146
+ WantedBy=multi-user.target
147
+ ```
148
+
149
+ Reload systemd and start the service.
150
+
151
+ ```shell
152
+ sudo systemctl daemon-reload
153
+ sudo systemctl enable ./twin-node.service
154
+ sudo systemctl start twin-node.service
155
+ ```
156
+
157
+ To check the status of the service.
158
+
159
+ ```shell
160
+ sudo systemctl status twin-node.service
161
+ ```
162
+
163
+ or
164
+
165
+ ```shell
166
+ sudo journalctl -u twin-node | tail
167
+ ```
168
+
169
+ ## Upgrade EC2 Instance
170
+
171
+ To upgrade a previous installation on an EC2 instance with the latest version.
172
+
173
+ ```shell
174
+ sudo systemctl stop twin-node.service
175
+ cd apps
176
+ git reset --hard
177
+ git pull
178
+ npm i
179
+ npm run dist
180
+ cd apps/node
181
+
182
+ # Update any env vars if necessary
183
+ # nano .env
184
+
185
+ # If you want to start from clean configuration you should remove the databases manually
186
+ # and also remove the engine-state file
187
+ # rm /home/ec2-user/twin-node/engine-state.json
188
+
189
+ # To perform a test run before launching the service permanently
190
+ # npm run start
191
+
192
+ sudo systemctl start twin-node.service
193
+ ```
@@ -0,0 +1,4 @@
1
+ # @twin.org/node - Deployment
2
+
3
+ - [Docker](./deployment-docker.md) - Guide to deploying with docker.
4
+ - [Amazon AWS EC2](./deployment-ec2.md) - Guide to deploying with Amazon AWS EC2.