Open danielblignaut opened 4 years ago
This didn't work for me, I would just get 401s for the session route. What I ended up doing was running the RCE API with PM2 instead of Passenger and adding a proxy configuration to the canvas apache config like here: https://github.com/instructure/canvas-rce-api/issues/6#issuecomment-616390845.
These instructions worked beautifully! I wish I could buy you a beer. Thanks so much.
I did a couple of things differently.
First, I was a little uncomfortable placing the environment variables within that folder, as they might be served publicly if file permissions aren't set properly. Rather than using a .env file, they can easily be defined in the Apache configuration file using SetEnv. Secondly, within app.js I added the following line (per what is now in the master branch):
global.fetch = require("node-fetch");
Otherwise a number of things, such as file upload, failed with TypeError: global.fetch is not a function.
I would of course +1 adding this as official documentation. Just glad I stumbled across it with Google.
Remember to enable it in Site Admin afterwards or your efforts will be in vain (I'm sure it's obvious to most, but not to a simpleton like me!)
Is there a way to test if RCE API is working? What should be displayed if I try to get /api/folders ?
@danielblignaut Thanks so much for your instructions. I follow your instructions, but I got following issues:
I got "ERR_TOO_MANY_REDIRECTS" and the api url become:
Do you have any suggestions on this issue? Thank you!
I do not need to change anything in original code to run RCE with passenger. my config
<VirtualHost *:443>
ServerName rce.example.com
DocumentRoot /home/rce/public_html/public
PassengerNodejs /snap/bin/node
PassengerAppRoot /home/rce/public_html
PassengerAppType node
PassengerStartupFile app.js
<Directory /home/rce/public_html/public>
Allow from all
Options All
Require all granted
</Directory>
</VirtualHost>
I was configuring the site following this tutorial but your approach I think it's better. However, I don't know if I messed up the configuration at some point, it raised an Internal Server Error when editing and images were not uploaded.
Hi, there. I already achieved to run canvas-rce-api in Apache2 Web Server + Passanger. You don't need to change the app.js and application.js files to run the code with Passenger, as @amg-web noticed. You can modify your canvas.conf file to add the nodejs app as a subdirectory or create subdomain and run canvas-rce-api.
As I didn't know how to add canvas-rce-api as subdirectory, I created a subdomain, but that requires unnecessary extra steps to add your subdomain to your DNS Register. After reading Passenger documentation, I found that adding a subdirectory is straightforward. Check this as reference.
This is my file creating a subdomain for the nodejs canvas-rce-api app:
<VirtualHost *:443>
ServerName subdomain.example.domain
DocumentRoot /path/to/my/app
PassengerAppRoot /path/to/my/app
PassengerAppType node
PassengerStartupFile app.js
<Directory /path/to/my/app>
Allow from all
Options -MultiViews
Require all granted
</Directory>
...
</VirtualHost>
However, you can edit the canvas.conf file that you already created for the rails application and edit it on this way:
<VirtualHost *:80>
# Your previous config is something like below
ServerName example.domain
DocumentRoot /path/to/my/app
<Directory /path/to/my/app>
Allow from all
Options -MultiViews
# Uncomment this if you're on Apache >= 2.4:
#Require all granted
</Directory>
# These have been added:
Alias /subapp /websites/secondapp/public
<Location /subapp>
PassengerBaseURI /subapp
PassengerAppRoot /websites/secondapp
PassengerAppType node
PassengerStartupFile app.js
</Location>
<Directory /websites/secondapp/public>
Allow from all
Options -MultiViews
# Uncomment this if you're on Apache >= 2.4:
#Require all granted
</Directory>
</VirtualHost>
After that, enable the new config and restart apache.
$ sudo a2ensite canvas.conf && sudo systemctl restart apache2
In theory, Passenger would be able to run node by itself, but if you find issues (as it happened to me), just do this:
$ whereis node
(In my case, located in /etc/apache2/mods-available/Passenger.conf)
### Begin automatically installed Phusion Passenger config snippet ###
<IfModule mod_passenger.c>
PassengerRoot /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini
PassengerDefaultRuby /usr/bin/passenger_free_ruby
PassengerNodejs YOUR_NODE_PATH_HERE
# MORE CONFIG LINES
...
</IfModule>
### End automatically installed Phusion Passenger config snippet ###
$ sudo a2enmod passenger
$ sudo systemctl restart apache2
So, the node app should run in apache without issues.
Thanks for sharing this, but this does not work any longer with the latest prod
canvas and rce-api setup as of today. This will cause 404 Not Found
for the /api/session
path - which RCE requires for trusting the incoming requests.
~~
Hi, there. I already achieved to run canvas-rce-api in Apache2 Web Server + Passanger. You don't need to change the app.js and application.js files to run the code with Passenger, as @amg-web noticed. You can modify your canvas.conf file to add the nodejs app as a subdirectory or create subdomain and run canvas-rce-api.
As I didn't know how to add canvas-rce-api as subdirectory, I created a subdomain, but that requires unnecessary extra steps to add your subdomain to your DNS Register. After reading Passenger documentation, I found that adding a subdirectory is straightforward. Check this as reference.
This is my file creating a subdomain for the nodejs canvas-rce-api app:
<VirtualHost *:443> ServerName subdomain.example.domain DocumentRoot /path/to/my/app PassengerAppRoot /path/to/my/app PassengerAppType node PassengerStartupFile app.js <Directory /path/to/my/app> Allow from all Options -MultiViews Require all granted </Directory> ... </VirtualHost>
However, you can edit the canvas.conf file that you already created for the rails application and edit it on this way:
<VirtualHost *:80> # Your previous config is something like below ServerName example.domain DocumentRoot /path/to/my/app <Directory /path/to/my/app> Allow from all Options -MultiViews # Uncomment this if you're on Apache >= 2.4: #Require all granted </Directory> # These have been added: Alias /subapp /websites/secondapp/public <Location /subapp> PassengerBaseURI /subapp PassengerAppRoot /websites/secondapp PassengerAppType node PassengerStartupFile app.js </Location> <Directory /websites/secondapp/public> Allow from all Options -MultiViews # Uncomment this if you're on Apache >= 2.4: #Require all granted </Directory> </VirtualHost>
After that, enable the new config and restart apache.
$ sudo a2ensite canvas.conf && sudo systemctl restart apache2
Troubleshooting
In theory, Passenger would be able to run node by itself, but if you find issues (as it happened to me), just do this:
Find Node location
$ whereis node
Edit Passenger.conf file
(In my case, located in /etc/apache2/mods-available/Passenger.conf)
### Begin automatically installed Phusion Passenger config snippet ### <IfModule mod_passenger.c> PassengerRoot /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini PassengerDefaultRuby /usr/bin/passenger_free_ruby PassengerNodejs YOUR_NODE_PATH_HERE # MORE CONFIG LINES ... </IfModule> ### End automatically installed Phusion Passenger config snippet ###
Enable mod and restart apache
$ sudo a2enmod passenger $ sudo systemctl restart apache2
So, the node app should run in apache without issues.
@ceekr Which are the changes of canvas-rce-api and prod? I have this config running on my prod env and I updated just two weeks ago. There are many ways that the config could go wrong and also many ways to setup.
I get this error while uploading an Image but if the image is a url it works. How do I resolve this
@ngerakam i am also facing the same problem. after started the rce api in port 3001 im also able to upload images via link but unable to upload images locally. any help would be appreciated.
check browser's dev console
this is the log im getting in browser console during my uploading of image after installing rce ,
Failed to load resource: the server responded with a status of 401 () /api/session:1
Failed to load resource: the server responded with a status of 401 ()
plugin.js:58 The Paste plugin failed to get canvas session data. (anonymous) @ plugin.js:58 /api/session:1
Failed to load resource: the server responded with a status of 401 ()
/api/session:1
Failed to load resource: the server responded with a status of 401 ()
api.js:53 Uncaught (in promise) Error at b (api.js:53:19) api.js:514
GET https://mydomain.in/api/session 401 (Unauthorized)
apiReallyFetch @ api.js:514
getSession @ api.js:99
o @ session.js:33
(anonymous) @ index.js:8
loadSession @ sidebarHandlers.js:34
(anonymous) @ UploadFileModal.js:114
Cs @ react-dom.production.min.js:211
$l @ react-dom.production.min.js:257
t.unstable_runWithPriority @ scheduler.production.min.js:19
so @ react-dom.production.min.js:122
Wl @ react-dom.production.min.js:257
Tl @ react-dom.production.min.js:239
(anonymous) @ react-dom.production.min.js:123
t.unstablerunWithPriority @ scheduler.production.min.js:19
so @ react-dom.production.min.js:122
po @ react-dom.production.min.js:123
uo @ react-dom.production.min.js:122
ql @ react-dom.production.min.js:240
kc @ react-dom.production.min.js:284
t.render @ react-dom.production.min.js:290
(anonymous) @ doFileUpload.js:60
(anonymous) @ doFileUpload.js:45
Promise.then (async)
ne @ doFileUpload.js:33
re @ clickCallback.js:20
(anonymous) @ plugin.js:86
commands.exec.
GET https://mydomain.in/api/session 401 (Unauthorized)
(anonymous) @ api.js:520
Promise.then (async)
(anonymous) @ api.js:519
Promise.then (async)
apiReallyFetch @ api.js:516
getSession @ api.js:99
o @ session.js:33
(anonymous) @ index.js:8
loadSession @ sidebarHandlers.js:34
(anonymous) @ UploadFileModal.js:114
Cs @ react-dom.production.min.js:211
$l @ react-dom.production.min.js:257
t.unstable_runWithPriority @ scheduler.production.min.js:19
so @ react-dom.production.min.js:122
Wl @ react-dom.production.min.js:257
Tl @ react-dom.production.min.js:239
(anonymous) @ react-dom.production.min.js:123
t.unstablerunWithPriority @ scheduler.production.min.js:19
so @ react-dom.production.min.js:122
po @ react-dom.production.min.js:123
uo @ react-dom.production.min.js:122
ql @ react-dom.production.min.js:240
kc @ react-dom.production.min.js:284
t.render @ react-dom.production.min.js:290
(anonymous) @ doFileUpload.js:60
(anonymous) @ doFileUpload.js:45
Promise.then (async)
ne @ doFileUpload.js:33
re @ clickCallback.js:20
(anonymous) @ plugin.js:86
commands.exec.
GET https://mydomain.in/api/session 401 (Unauthorized)
apiReallyFetch @ api.js:514 getSession @ api.js:99 apiFetch @ api.js:505 fetchPage @ api.js:155 fetchMediaFolder @ api.js:352 (anonymous) @ upload.js:369 (anonymous) @ index.js:8 startMediaUpload @ sidebarHandlers.js:59 q @ UploadFile.js:73 l @ doFileUpload.js:54 onSubmit @ UploadFileModal.js:137 s @ react-dom.production.min.js:14 h @ react-dom.production.min.js:14 f @ react-dom.production.min.js:14 g @ react-dom.production.min.js:15 ft @ react-dom.production.min.js:52 pt @ react-dom.production.min.js:51 _t @ react-dom.production.min.js:52 wt @ react-dom.production.min.js:56 P @ react-dom.production.min.js:287 V @ react-dom.production.min.js:19 cn @ react-dom.production.min.js:70 ln @ react-dom.production.min.js:69 t.unstable_runWithPriority @ scheduler.production.min.js:19 so @ react-dom.production.min.js:122 H @ react-dom.production.min.js:287 an @ react-dom.production.min.js:68 c @ rocket-loader.min.js:1 Show 17 more frames Show less api.js:520
GET https://mydomain.in/api/session 401 (Unauthorized)
(anonymous) @ api.js:520 Promise.then (async) (anonymous) @ api.js:519 Promise.then (async) apiReallyFetch @ api.js:516 getSession @ api.js:99 apiFetch @ api.js:505 fetchPage @ api.js:155 fetchMediaFolder @ api.js:352 (anonymous) @ upload.js:369 (anonymous) @ index.js:8 startMediaUpload @ sidebarHandlers.js:59 q @ UploadFile.js:73 l @ doFileUpload.js:54 onSubmit @ UploadFileModal.js:137 s @ react-dom.production.min.js:14 h @ react-dom.production.min.js:14 f @ react-dom.production.min.js:14 g @ react-dom.production.min.js:15 ft @ react-dom.production.min.js:52 pt @ react-dom.production.min.js:51 _t @ react-dom.production.min.js:52 wt @ react-dom.production.min.js:56 P @ react-dom.production.min.js:287 V @ react-dom.production.min.js:19 cn @ react-dom.production.min.js:70 ln @ react-dom.production.min.js:69 t.unstable_runWithPriority @ scheduler.production.min.js:19 so @ react-dom.production.min.js:122 H @ react-dom.production.min.js:287 an @ react-dom.production.min.js:68 c @ rocket-loader.min.js:1 Show 17 more frames Show less upload.js:391 Fetching the media folder failed. Error at b (api.js:53:19) at async k.apiFetch (api.js:504:15) (anonymous) @ upload.js:391 Promise.catch (async) (anonymous) @ upload.js:387 (anonymous) @ index.js:8 startMediaUpload @ sidebarHandlers.js:59 q @ UploadFile.js:73 l @ doFileUpload.js:54 onSubmit @ UploadFileModal.js:137 s @ react-dom.production.min.js:14 h @ react-dom.production.min.js:14 f @ react-dom.production.min.js:14 g @ react-dom.production.min.js:15 ft @ react-dom.production.min.js:52 pt @ react-dom.production.min.js:51 _t @ react-dom.production.min.js:52 wt @ react-dom.production.min.js:56 P @ react-dom.production.min.js:287 V @ react-dom.production.min.js:19 cn @ react-dom.production.min.js:70 ln @ react-dom.production.min.js:69 t.unstable_runWithPriority @ scheduler.production.min.js:19 so @ react-dom.production.min.js:122 H @ react-dom.production.min.js:287 an @ react-dom.production.min.js:68 c @ rocket-loader.min.js:1 Show 17 more frames
can anyone help me in recovering from it??
This is my canvas.conf file,
<VirtualHost *:80> ServerName dev.mydomain.in DocumentRoot /var/canvas/public PassengerRuby /usr/bin/ruby3.1 PassengerAppEnv production RailsEnv production <Directory /var/canvas/public> AllowOverride all Options -MultiViews Require all granted
This is my canvas-ssl.conf file,
and i am running canvas-rce api in port 3001.
if you try to use rce in same domain find the respective ticket on github
can you help me in find that ticket? Thanks in advance.
@vignesh-pandian-p
https://github.com/instructure/canvas-rce-api/issues/6
It's amazing that this is now required by canvas lms stable releases moving forward but there's a HUGE lack of documentation around production configuration or any configuration really.
On that note, for any lost souls, here's my implementation to get it working.
Disclaimer 1: I have not reviewed and made sure that all my steps are secure for a production environment Disclaimer 2: This is not fully tested but course files insertion in canvas is now working and the API endpoints appear to be responding.
Requirements / Who this is for:
Instructions
Configure canvas core rce settings
First we need to configure canvas core's encryption strings for generating JWT tokens. Because our rce api server needs to be able to authenticate valid users, these config strings need to be shared with the rce api (we do this in the following step). We will also tell canvas core where our rce api server is hosted (in my case, its on the same server and url as the canvas install)
navigate to the dynamic_settings.yml config file. If you're using Consul, you proabbly need to do something else to update these values
change "development" to "production" on line 7 change astringthatisactually32byteslong to a random string on line 14 (take note of this value as its later referenced as ECOSYSTEM_KEY_VALUE) change astringthatisactually32byteslong to a random string on line 15 (take note of this value as its later referenced as ECOSYSTEM_SECRET_VALUE) change rce.docker to yourcanvasdomain.com on line 31 (use whatever your domain is. dont include http /https)
a 32 byte long string is a string that is 32 characters long. Keep it alphanumeric. Use a random string generator.
update permisions for safety
Install canvas-rce-api
We need to actually install this library / server onto our box and configure it.
ssh into your box, install canvas-rce-api wherever you would like (note the directory for that referenced as RCE_APP_DIRECTORY later on)
You're now going to set the .env variables.
and update the values to below. I deleted CIPHER_PASSWORD completely. ECOSYSTEM_SECRET_VALUE and ECOSYSTEM_KEY_VALUE is referenced in the previous step as it is a core canvas project config value. Please enter their actual values below that you entered in the previous step, not ECOSYSTEM_SECRET_VALUE or ECOSYSTEM_KEY_VALUE
PORT=3001 NODE_ENV=production STATSD_HOST=127.0.0.1 STATSD_PORT=8125 STATS_PREFIX=rceapi ECOSYSTEM_SECRET=ECOSYSTEM_SECRET_VALUE ECOSYSTEM_KEY=ECOSYSTEM_KEY_VALUE CIPHER_PASSWORD=TEMP_PASSWORD
now lets update permissions again
Edit canvas-rce-api to run on phusion
Because we are making use of apache2 and phusion for our web server requests and SSL configuration, it makes sesnse to run this rce api inside phusion instead of standalone. To do that, we will need to update our nodejs code to check if phusion is installed, and if it is, let phusion manage what local port our application is running on. When we then configure our apache server and phusion settings in the next step, phusion will proxy all external requests meant for the rce server to the rce server on the local port that phusion has specified in our app :) lots of words.
and add the below js code to the new app.js file
save this file. then:
and add the below
save file. You can see in the above, we are checking if phusion passenger is installed / running and if it is, we listen on 'passenger' otherwise we just use the port in our .env file.
Again, update permissions:
Update apache config & routes
now, this part is a bit of a mess. Basically from my findings, canvas has api endpoints on {yourdomain}/api .The issue here is that there is not specific subdirectory dedicated to the rce editor api routes, instead its a mix and match of rce server managed api routes and canvas core managed api routes. To get around this, I hardcoded all of the rce server api routes into a regular expression that we are going to add to our apache config below. Our code below basically says if apache matches a route to our regex, then instead of passing that route onto canvas core to manage, pass it to the rce server. Our code below also tells phusion passenger that we have an additional web app (our rce server)
the canvas.conf is whatever you configured your site to be in the production start tutorial of the core canvas system.
In this file, you should see 1 or 2 root entries for VirtualHost. The first VirtualHost should be for port 80 (all http traffic). Before the closing tag for the http traffic, add the below
Please update:
Please repeat the same process for your second VirtualHost entry if you have one (should be for ssl traffic).
restart apache! and you should be in business. There may be some mistyped commands above, please comment if this does not work for you and I can try assist however I'm no canvas evangelist so I probably won't be able to offer too much advice