Installing Quilgo Proctoring in Canvas
Quilgo Proctoring is installed once for your whole Canvas account. The setup has two parts: an LTI 1.3 app, and one proctoring snippet in your Canvas theme. Both are required.
Before you begin
- You need an account administrator role in Canvas — the steps below use the Admin area.
- The whole installation is a one-off. Teachers or students do not have to participate in the installation process.
Register the app
Quilgo supports Canvas automatic (dynamic) registration, so there is nothing to type by hand.
- In Canvas, go to Admin → Developer Keys → + Developer Key → LTI Registration.

Developer Keys → + Developer Key → LTI Registration. - Paste the registration address:
https://quilgo-host/lti/register
Paste your Quilgo registration address and click Continue. The address in the example points at a test server. - A Quilgo page opens inside Canvas. Click Install.

The Quilgo page inside the Canvas dialog — click Install. - When Canvas shows its confirmation dialog, click the Enable & Close button.

Canvas shows the permissions and placements it is about to create — click Enable & Close.
Turn the key on and make the app available
Canvas has now created the new key. Ensure it is ON and follow these steps to activate it:
- Go to Developer Keys, find Quilgo Proctoring and make sure its State is ON (switch it if it isn’t).

The Quilgo Proctoring row in Developer Keys — State must be the green toggle. - Open the key’s View in Canvas Apps link. Under Availability and Exceptions, click the edit (pencil) button, set the app to Available, and click Save.

View in Canvas Apps sits in the key’s Details column. 
On the app page, open Availability and Exceptions and click the pencil button. 
Switch Not Available → Available, then Save. - Reload the page — Quilgo Proctoring appears in the Admin sidebar.
Upload the proctoring snippet to your theme
- Download the snippet: in the Canvas left navigation open Admin → your account, then click Quilgo Proctoring in the account menu on the left (it appeared there after Step 2). On the page that opens, click Download Proctoring snippet — this saves quilgo-canvas.js to your computer.

The account-level Quilgo Proctoring page, opened from the Admin sidebar. 
In Integration & Install Health, click Download proctoring snippet. - Go to Admin → Themes, open your active theme in the Theme Editor and make sure the Upload tab is visible.

Admin → Themes — hover your current theme and click Open in Theme Editor. 
The Upload tab with the JavaScript file slot. No Upload tab? Go to Admin → Settings, scroll to the bottom of the account settings page, tick Custom CSS/JavaScript overrides, save, then reopen the Theme Editor.

Admin → Settings → Features: tick Custom CSS/JavaScript overrides. - On the Upload tab, check whether a JavaScript file is already uploaded:
- No file: nothing to combine — you will upload the downloaded quilgo-canvas.js as is.

An empty JavaScript file slot — nothing to preserve, upload the snippet as is. - A file already exists: click the View File button next to the JavaScript file uploader and save the file to your computer. Open both files in a text editor and paste the snippet’s entire code at the very end of your existing file. Save the result with a .js extension and continue with the combined file.
Important: add the snippet at the end of the file. Canvas allows only one JavaScript file per theme — uploading the snippet alone would replace your existing code.
- No file: nothing to combine — you will upload the downloaded quilgo-canvas.js as is.
- Upload the file in the JavaScript file slot on the Upload tab.
- Click Preview Your Changes, then Save theme and Apply theme.

The file is attached — click Preview Your Changes, then Save theme in the green bar.
Activate your account
Until the account is activated, proctoring settings in quiz menus stay locked: teachers see “Please ask your administrator to activate the account to enable proctoring”, and administrators see the activation button right there.
- In the Admin sidebar, open Quilgo Proctoring and click Activate your account. The same button sits in two places on that page — at the bottom of Subscription Overview, and in the Activation account row of Integration & Install Health; either one opens the Quilgo dashboard on the sign-up page.

Both entry points: the button under Subscription Overview and the link in the Activation account row. - Create your Quilgo account there (or log in if you already have one) and confirm your email. The dashboard already knows which Canvas site you arrived from — create an organization (it holds billing, licences and team access) and click Connect site to finish the link.

Sign up with an email address, or continue with Google. 
After confirming the email, click Log into my dashboard. 
The Canvas site is already identified; name the organization and click Connect site. 
Confirmation that proctoring is now active on the site. - Back in Canvas, refresh the Quilgo Proctoring page — the Activation account row in Integration & Install Health should turn Active, and proctoring settings unlock for teachers.
Verify the installation
- In the Canvas Admin sidebar, open Quilgo Proctoring.
- Check the Integration & Install Health panel: Registration, Activation account and Proctoring integration should all read Active, and Theme file last seen should show a recent time (it refreshes within a few minutes of anyone viewing a Canvas page — reload a Canvas page, then refresh this panel).

A finished installation: all three rows Active, a recent Theme file last seen, and the plan visible in Subscription Overview. - Run a real test: open any quiz, choose Quilgo Proctoring from the quiz menu, tick Enable proctoring, pick the tracking methods and Save, then take the quiz as a test student. Open it with View as Student: before the attempt starts, a Start attempt dialog lists the tracking you switched on and asks for exactly those permissions — screen, camera, or both. Nothing is requested for methods you left off.

The quiz ⋮ menu in Quizzes — Quilgo Proctoring is the last entry. 
Turn Enable Proctoring on, then pick the tracking methods and Save Settings. 
View as Student, top right of the course, opens Canvas as a test student. 
The student's Start attempt dialog — here only screen tracking was on, so it asks for screen access.
That’s the whole installation. From here teachers just tick Enable proctoring per quiz — no per-course setup is needed.
Where teachers find it
- Classic Quizzes: open the quiz and click the three-dot menu (⋮) in the top-right corner — Quilgo Proctoring appears there.
- New Quizzes: open the assignment — Quilgo Proctoring appears in the assignment menu.
- Administrators: the account-level page (Admin sidebar → Quilgo Proctoring) shows install health and results.
- Students never open the tool. Proctoring starts on the quiz page itself when the teacher has switched it on.
Troubleshooting
The registration window shows an error
The registration link Canvas issues is valid for one attempt only. Close the dialog and start again from Admin → Developer Keys → + Developer Key → LTI Registration.
No Upload tab (or no JavaScript slot) in the Theme Editor
Custom JavaScript uploads are disabled on your account. Go to Admin → Settings, scroll to the bottom of the account settings page, tick Custom CSS/JavaScript overrides, save, then reopen the Theme Editor — the Upload tab appears. On a self-hosted Canvas, if the tab is still missing after that, check item 2 of the self-hosted prerequisites.
“Theme file last seen: never”, or nothing is recorded
The theme file is missing or the theme was saved but not applied. Re-open the Theme Editor, confirm quilgo-canvas.js is uploaded under JavaScript, and click Apply theme. The panel updates within a few minutes of the first page view.
Browser console says “[Quilgo] this Canvas is not a known installation”
The theme file is in place, but your Canvas domain isn’t linked to a registration yet. Open Quilgo Proctoring from the Admin sidebar once (this links the domain automatically), or contact us if it persists.
“This app has been locked by an administrator and is not available for installation”
Appears on + App → By Client ID when your Canvas has the “Lock LTI Registrations” feature enabled and the app is marked as locked for client-ID deployment. Either unlock the app on its page in Canvas Apps (Admin → Apps → Manage), or skip the legacy install entirely and make the app available there via Availability and Exceptions — both paths end in the same installed state.
A student sees “Students are proctored through the quiz page, not this launch”
Expected — the student opened the tool link directly. They should simply take the quiz; proctoring starts there.
Anything else
Write to hello@quilgo.com — include your Canvas domain and a screenshot of the Integration & Install Health panel if you can.
Manual installation (fallback)
Use this only if automatic registration is unavailable on your Canvas instance — for example, if your institution has disabled dynamic registration.
- Go to Admin → Developer Keys → + Developer Key → + LTI Key.
- In Method, choose Enter URL and paste:
With Enter URL, your Canvas server fetches this address itself. If saving fails — common on self-hosted servers that block outbound traffic — open the URL in your browser, copy the JSON, and use the Paste JSON method instead.
https://quilgo-host/lti/canvas-config.json - Set Key Name to Quilgo Proctoring and save. Switch the key’s State to ON.
- Copy the key’s Client ID — the long number shown in the Details column.
- Add the app to your account: Admin → Settings → Apps → View App Configurations → + App, set Configuration Type to By Client ID, paste the Client ID, then Submit → Install.
- Email the Client ID and your Canvas domain (for example
canvas.school.edu) to hello@quilgo.com — we activate the installation on our side.Why this step exists: a manually created key is known only to Canvas — unlike automatic registration, nothing tells Quilgo about it. Your installation still connects itself the first time someone opens Quilgo Proctoring in Canvas, but until then the proctoring snippet in your theme has nothing to attach to. Sending us the Client ID and domain activates the installation ahead of that first launch, so recording works immediately. On a self-hosted Canvas this step is essential rather than optional: self-hosted instances issue non-unique Client IDs, and the domain (together with the issuer from the prerequisites) is what distinguishes your installation from another school’s.
- Continue with Step 3 (theme snippet), Step 4 (activation) and Step 5 (verification) above.
Self-hosted Canvas prerequisites
Quilgo works on any Canvas. Canvas Cloud (*.instructure.com) needs none of this — skip this section. A self-hosted Canvas must have the following configured. All of it is standard Canvas administration required by any LTI 1.3 tool, and every item can be verified in about ten minutes — before installing anything.
1 · LTI signing keys
Check: open this address in a browser:
https://your-canvas/api/lti/security/jwksIt must return one or more keys. {"keys":[]} means Canvas has nothing to sign launches with — every LTI 1.3 tool will fail.
Fix (Canvas server): generate three keys in the Rails console (bundle exec rails console) by running this three times:
key = OpenSSL::PKey::RSA.generate(2048); puts key.to_jwk(kid: Time.now.utc.iso8601).to_jsonPlace the three outputs in config/dynamic_settings.yml under store.canvas.lti-keys as jwk-past.json, jwk-present.json and jwk-future.json, then restart Canvas.
2 · Theme JavaScript delivery
Check: in Admin → Settings (bottom of the page) enable Custom CSS/JavaScript overrides — without it the Upload tab in the Theme Editor does not exist. Upload any JS file in the Theme Editor and apply the theme, then open any Canvas page, view its source, find the js_overrides script tag and open its URL. It must return the script, not an error page. A 4xx here means Canvas’s file storage cannot serve uploads.
Fix (Canvas server): file storage configuration in config/file_store.yml (local path and permissions, or S3 credentials); the exact failure is in the Canvas production logs for that download request.
3 · LTI 1.3 machinery
Check: in Admin → Developer Keys create any LTI key, then open any LTI placement. A “Something broke” error at either step appears before the external tool is contacted and indicates a Canvas configuration problem, not a tool problem.
Fix (Canvas server): the stack trace is in the Canvas error logs; typical causes are a missing or broken Rails cache (Redis) or an absent dynamic_settings.yml.
4 · Stable issuer
Check (Canvas server): run grep lti_iss config/security.yml and send us the value. Launches are validated against it, and changing it later invalidates the installation. The default is https://canvas.instructure.com, but self-hosted instances can change it.
5 · Environment basics
- Recent Canvas version — run a current open-source release; old releases are an untested failure class.
- HTTPS with a valid certificate on the Canvas domain — the tool runs in an iframe and browsers refuse mixed content.
- Server clock synced via NTP — LTI launches are short-lived signed tokens; minutes of skew make every launch “expired”.
- Outbound HTTPS from the Canvas server to your Quilgo server — Canvas fetches the tool configuration during registration and its JWKS when issuing service tokens.
- Reverse proxy passes headers through — Quilgo identifies which Canvas a request came from by
Origin/Referer; a proxy stripping them breaks identification. A restrictive Content-Security-Policy in front of Canvas must allow scripts from your Quilgo server’s domain.
Data and permissions
- Quilgo receives the name and email of the user in each signed launch (Canvas privacy level “Public”).
- The app requests exactly one LTI service: course membership, read-only (Names and Role Provisioning Service) — used to match attempts to students.
- Quilgo never writes grades and requests no gradebook or Canvas API scopes.
- Installing again (for example after re-running registration) does not create a second account — Canvas instances are recognised and merged automatically.
Technical reference
For change-management or security review. All URLs are on your Quilgo server.
| Item | Value |
|---|---|
| Dynamic registration URL | https://quilgo-host/lti/register |
| Manual JSON configuration | https://quilgo-host/lti/canvas-config.json |
| OIDC login (initiation) URL | https://quilgo-host/lti/login |
| Target link URI / redirect URI | https://quilgo-host/lti/launch |
| Public JWK set | https://quilgo-host/lti/jwks |
| Theme proctoring snippet | https://quilgo-host/loader/theme.js → quilgo-canvas.js |
| Placements | Account navigation, Quiz menu, Assignment menu — all titled “Quilgo Proctoring” |
| LTI scopes | lti-nrps/scope/contextmembership.readonly only |
| Custom fields | $Canvas.course.id, $Canvas.assignment.id, $Canvas.user.id, $Canvas.api.domain |
| Signing | LTI 1.3 / OIDC, RS256, private_key_jwt |
Appendix · Local development (Quilgo team)
Internal. Nothing in this appendix applies to customers — their Canvas and our server share one public domain, so none of these quirks exist for them. Remove this section from any copy shared outside the team.
The full stack
| Service | Port | How to run |
|---|---|---|
| plasm API (Canvas build) | 8083 | pnpm start:dev-server in plasm (INTEGRATION_TYPE=canvas in .env) |
| plasm queue workers | — | pnpm start:dev-server:workers in plasm — without it (and the report worker) results show “report is not ready yet” forever |
| plasm report worker | — | pnpm start:dev-server:report-worker in plasm |
| plasm billing process | 8483 | pnpm start:dev-server:billing in plasm — the dashboard’s backend API (dev port = PORT + 400); without it the dashboard login shows a 404 |
| Dashboard front-end | 3005 | dev server in plasm/front-end |
| Canvas LMS | 3000 | Docker compose in canvas-lms (canvas-lms-web-1) |
| Billing | 8181 | pnpm start:dev-server in billing |
| Media processor | 8686 | Docker container quilgo-media-processor |
| Pub/Sub emulator | 8681 | Docker container plasm-pubsub |
Who resolves which URL
Canvas runs in Docker, the tool on the host — so localhost names two different machines. Browser-side URLs must stay localhost:8083; anything the Canvas server fetches needs host.docker.internal:8083.
| URL | Dereferenced by | Use |
|---|---|---|
OIDC login, launch, /lti/register page, /loader/theme.js | Browser (host) | localhost:8083 |
“Enter URL” fetch of canvas-config.json, tool JWKS for NRPS tokens | Canvas server (container) | host.docker.internal:8083 |
- Enter URL: paste
http://host.docker.internal:8083/lti/canvas-config.json— or use Paste JSON with the config opened in the browser. - NRPS: after creating a manual key, edit its Public JWK URL to
http://host.docker.internal:8083/lti/jwks— the container cannot reachlocalhost:8083when validating our token requests. - Manual keys need our side too:
pnpm lti:register-customer --client-id=<id> --domain=localhost:3000 --write(dry run without--write). - Emails:
POSTMARK=POSTMARK_API_TEST— confirmation emails go to Postmark test mode; verify by send logs, no real inbox.
Reset to a from-scratch state
The wipe commands (our DB, keyed by domain = 'localhost:3000' so megasobaken survives, plus the Canvas-side cleanup) live in the repo: plasm/docs/local-canvas-dev.md.
Verify the clean state after running them (the theme file stays — it names no customer):
curl "http://localhost:8083/loader/identity?host=localhost:3000" -H "Origin: http://localhost:3000"
# → {} (unknown installation — correct from-scratch state)