Spin Up Your Own Terracotta Instance

Build, configure, and deploy Terracotta

Terracotta is free and open source, so if you’d like to create your own instance, you’re welcome to do so by following the instructions below.

Building Terracotta

The Terracotta code is available in this repository: Terracotta GitHub , and the current stable version is the latest tag in GitHub. Use the README file there to build Terracotta. 

Terracotta is a java Spring Boot v3 application that uses Maven to build. The user interface (UI) is built with Vue.js v2 and needs to run yarn to build all the static files. The maven command includes everything necessary.

To generate a jar file (that will be created in the “target” directory) this command needs to be executed: 

  • mvn clean install  

*Please note, if test errors occur, try this command: 

  • mvn clean install -DskipTests=true 

*Please also note, to skip the yarn build, you can use -Dskip.yarn 

Configuring Terracotta

Application properties file 

To configure Terracotta, we will use an application properties file. The file can be named anything because we will define the name in the java command that launches the jar. A common name, however, would be “application.properties.”

This is a Spring Boot application, so any Spring configuration could be applied in this file.

Here is a line-by-line explanation of the configuration: 

  • (Optional) Server port - in case it needs to run in a port different from the default 8080: 

server.port=8090  

  • Thymeleaf necessary configuration:  

spring.thymeleaf.mode=HTML5 

  • Logging path - If we use nohup these will be ignored, but in case we run the jar without nohup in the server this configuration will indicate where to write the logs: 

logging.file=/path/terracotta.log   

  • Logging level - Levels can change to DEBUG for more detailed information (we do not recommend this in prod, or if so, only for short tests, as the log can become very long). 

logging.level.org.springframework.web=INFO 

logging.level.org.springframework.security=INFO 

logging.level.org.hibernate=ERROR 

logging.level.edu.iu.terracotta=INFO 

  • Database connection 

spring.jpa.hibernate.ddl-auto=none 

spring.datasource.url=jdbc:mysql://<mysql_server_url>:<port>/<database>    

spring.datasource.driverClassName=com.mysql.cj.jdbc.Driver 

spring.datasource.username=<username> 

spring.datasource.password=<password> 

spring.liquibase.change-log=classpath:/db/changelog/changelog-master.xml 

  • SSL management with the AWS load balancer in front. 

security.require-ssl=true  

server.tomcat.remoteip.remote-ip-header=x-forwarded-for 

server.tomcat.remoteip.protocol-header=x-forwarded-proto 

security.headers.frame=false 

  • Public and private keys - It is necessary to generate a NEW and UNIQUE pair of public and private keys and add them to the configuration file. 

oicd.privatekey=<-----BEGIN PRIVATE KEY-----MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC2QJCkV2gFoQD2z7dQRq7g5qIxPaZJJZAJ07wPxdAJiyuWbo0bMOvH//5IqmOnUdal7iNYtDKwr9Cx6UMq...72wuT8RzsVTPwN9uKZOlm/sHd7KtETaMXRM94mT/uisQ9QahX48tw/c4miu+Sv2xWwQ1sNJ4OXzO/tir0uLgMp6XcA==-----END PRIVATE KEY----->

oicd.publickey=<-----BEGIN PUBLIC KEY-----MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtkCQpFdoBaEA9s+3UE...Q4k+79zbOxbvDSeuLLV0mAvM85k1m4lJMdOkmyTisx9BwvTamZnjsHA8krV2LeplSYPmzraXLbopAmSJGHibhMFpEfS6rwHaArNZFZ6vJBdWpTXd+QIDAQAB-----END PUBLIC KEY----->

  • Application-specific properties - The application url is very important, as we use it to build some links.  

application.url=https://<tool_url> 

application.name= Terracotta DEV 1 

application.description=The Terracotta tool 

  • In case we want to load data in the first start of the application from a place that is not the sample data provided in the jar file: 

initial.lti.data.location=classpath:data/ 

  • To edit the configuration using the /config/ API, we need to define a user and password. If we don’t define it, the user will be admin, and the password will be randomly generated and displayed in the log when the tool starts:  

terracotta.admin.user = <admin_user

terracotta.admin.password = <password

  • Where the files will be uploaded - This can be linked to any external storage and can be accessed via a normal path. NOTE: this requires an existing folder that will need to be manually created: 

upload.path=/the_path/terracotta_files 

  • To overwrite the cron schedule (if not configured, it will run every 24 hours): 

scheduled.deleteoldtokens.cron=*/50 * * * * * 

  • To configure Caliper: The first command enables sending the events; the second enables saving the events in the database. The others are the necessary configurations to create the sensor and connect with the learning record store (LRS). 

  • caliper.send will enable sending (or not) caliper events to the default server for the entities that have not defined individual caliper LRSs (default = false) 

  • caliper.store-db will enable storage in the db for the caliper events generated (all of them, not only the ones with the default configuration)  (default = false) 

  • The rest are the parameters needed to configure the caliper sensor. The ones in bold are good as default values:  

caliper.send=true 

caliper.store-db=true 

caliper.sensor-id = 123 

caliper.client-id=1231 

caliper.api-key = Bearer fdf7fc7f-8a71 

caliper.connection-timeout = 10000 

caliper.content-type = application/json 

caliper.host = https://caliper.imsglobal.org/caliper/fdf7fc7f-8a71-6e0b/message 

caliper.socket-timeout = 10000 

Other configurations 

  • Remember to create the file folder in the path you defined in the application folder; do the same if you define a folder to send the logs or to load the initial data. 

Deploying Terracotta

Spring Boot tool deployments: Deploying Spring Boot Applications :: Spring Boot  

The basic deployment consists of these steps: 

  1. Stop running the current version of Terracotta. 

  2. Replace the old jar with the newly generated jar file. 

  3. Restart Terracotta, launching the jar. 

This is one example of the commands used in the dev and test servers to launch the jar file (there might by another valid way to do so): 

nohup java -jar terracotta.jar --spring.config.location=application-local.properties &

This supposes that the jar file and properties file are in the same folder; this can be modified to indicate the correct path to the files.  

Configuring LTI and Caliper 

To configure the tool to work in Canvas (and Canvas to work with the tool), follow the steps detailed below. 

Configure the tool in Canvas 

  1. Configure a new Development Key for LTI in Canvas (Admin -> Development Keys) 

Below, you will find an example JSON configuration where the <tool_url> should be updated in the last lines.    

This configuration ("windowTarget": "_blank") opens Terracotta in a new window, which is necessary to make it work in Safari and Firefox (it works without this configuration in Chrome). Please note that Terracotta is not currently compatible with Edge.

NOTE: In the left-had configuration page menu, the redirect url must be:  https://<tool_url>/lti3 

    "title": "Terracotta", 

    "scopes": [ 

        "https://purl.imsglobal.org/spec/lti-ags/scope/lineitem.readonly", 

        "https://purl.imsglobal.org/spec/lti-ags/scope/lineitem", 

        "https://purl.imsglobal.org/spec/lti-ags/scope/result.readonly", 

        "https://purl.imsglobal.org/spec/lti-ags/scope/score", 

        "https://purl.imsglobal.org/spec/lti-nrps/scope/contextmembership.readonly", 

        "https://canvas.instructure.com/lti/account_lookup/scope/show

    ], 

    "extensions": [ 

        { 

            "platform": "canvas.instructure.com", 

            "settings": { 

                "platform": "canvas.instructure.com", 

                "placements": [ 

                    { 

                        "enabled": true, 

                        "placement": "course_navigation", 

                        "message_type": "LtiResourceLinkRequest", 

                        "windowTarget": "_blank" 

                    } 

                ] 

            }, 

            "privacy_level": "public" 

        } 

    ], 

    "public_jwk": {}, 

    "description": "The terracotta tool for educational experiments", 

    "custom_fields": { 

        "due_at": "$Canvas.assignment.dueAt.iso8601", 

        "lock_at": "$Canvas.assignment.lockAt.iso8601", 

        "unlock_at": "$Canvas.assignment.unlockAt.iso8601", 

        "canvas_user_id": "$Canvas.user.id", 

        "canvas_login_id": "$Canvas.user.loginId", 

        "canvas_course_id": "$Canvas.course.id", 

        "canvas_user_name": "$User.username", 

        "canvas_assignment_id": "$Canvas.assignment.id", 

        "canvas_user_global_id": "$Canvas.user.globalId", 

        "allowed_attempts": "$Canvas.assignment.allowedAttempts", 

        "student_attempts": "$Canvas.assignment.submission.studentAttempts" 

    }, 

    "public_jwk_url": "https://<tool_url>/jwks/jwk", 

    "target_link_uri": "https://<tool_url>/lti3", 

    "oidc_initiation_url": "https://<tool_url>/oidc/login_initiations" 

  1. Once this is created, it must be enabled, with the state switch set to “ON”. Take note of the key id because it will become the “client_id.”  

  1. Finally, “deploy” the tool in Canvas (Admin -> Settings -> Apps -> View -> Apps Configuration -> + App). Change the configuration type to “By Client ID” and introduce the ID from the previous step. 

After clicking through to submit and accept, you will see Terracotta in the list of tools. You can then look in the tool’s menu for its deployment id (keep that number, too). 

Configure the API token in Canvas 

To create assignments, send grades, and read grades and outcomes, you will need an API token from Canvas. 

You will need an admin user with permissions to create assignments and read/send grades. 

Create the user (Account -> Settings -> Approved Integrations -> +New Access Token) and copy the value. You will need it for the configuration. 

Configure the LMS in Terracotta 

With the client_id and the deployment_id, you can configure Terracotta.

To do that, we need to add a row in the iss_configuration table on the Terracotta side.

You can do that directly with SQL or with any database tool that provides a UI to write in a database, like MySQLAdmin or DBeaver. You can also use the config API.

To use the config API, we need to use basic authentication to access to “our_tool_url/config/” with these values: 
terracotta.admin.user = <admin_user

terracotta.admin.password = <password

Here is an example of a configuration to POST: 

{ 

"iss": "https://canvas.instructure.com", 

"clientId": "97140000000000216", 

"oidcEndpoint": "https://terracotta.instructure.com/api/lti/authorize", 

"jwksEndpoint": "https://terracotta.instructure.com/api/lti/security/jwks", 

"oAuth2TokenUrl": "https://terracotta.instructure.com/login/oauth2/token", 

"oAuth2TokenAud": null

"deploymentId": "448:5440a08422ab1ee7794a0588b5e4cb4a094c4256", 

"apiToken": "9714~yidT975c2v3MT...WrM\n", 

"baseUrl": "https://terracotta.instructure.com", 

"caliperConfiguration": null

"caliperSensorId": null

"caliperClientId": null

"caliperApiKey": null

"caliperConnectionTimeout": null

"caliperContentType": null

"caliperHost": null

"caliperSocketTimeOut": null 

} 

  • These values - iss, oidcEndpoint, jwksEndpoint and oAuth2TokenUrl - should be configured as explained at this link: 
    # Manually Configuring LTI Advantage Tools - Canvas LMS REST API Documentation  

  • oAuth2TokenAud can be null (it would be needed for D2L, but not Canvas) 

  • clientId and deploymentId: must be the same as what you configured in Canvas 

  • apiToken: use the one created in Canvas 

  • baseUrl: the url of the Canvas instance, needed to create the API calls 

  • caliperConfiguration: a Boolean that indicates if you need to use a specific caliper configuration or not.   

  • If set to true, we will always send events to that configuration.  

  • If false, we won’t send events. 

  • If null, we will use the default value in the applications properties file.  

  • caliper *:  same values explained in the configuration file.  

Once this row is configured in the iss_configuration table, Terracotta should be able to receive LTI requests from Canvas.  

AWS Infrastructure deployment 

Test environment AWS resources deployment 

Note: The instructions below are “high level”; they are the steps to deploy the AWS resources to support the application, but each of the steps listed below may require a few steps as well. 

  1. Create a VPC with: 

  2. at least 3 zones: (public, private, protected) 

  3. at least 2 subnets per zone 

  4. Create the security groups for: 

  5. the application server 

  6. the bastion server 

  7. the rds instance 

  8. the load balancer 

  9. Create the key pair to use with the bastion and application servers 

  10. Create a KMS key for the environment/deployment 

  11. Create the bastion server in the public zone 

  12. Configure the bastion server to allow ssh connections from specific ips (those allow to have shell access to the bastion/app servers) 

  13. Configure the application server security groups to allow ssh connections from the bastion server 

  14. Create the application server in the private zone 

  15. Create the rds instance in the protected zones, enabled encryption using the KMS key that was created before 

  16. Configure the rds security group to allow MySQL connections from the application server 

  17. Create a target group with the proper port where the application will run on the application server (this most likely will be 8080) 

  18. Add the application server to the target group 

  19. Create an internet facing Application Load Balancer (alb) in the public zone: 

    1. configure a redirection from 80 to 443

    2. configure port 443 to forward to the target group of the application server

    3. configure the alb security group to accept connections from anywhere to ports 80 and 443 

Please keep in mind that “local” accounts must be created in both the bastion and application servers for people that need ssh/shell access to them.  

Test environment diagram 

 

Prod environment AWS resources deployment 

The deployment for the PROD environment would be the same as the ones for the TEST environment, except that for PROD the recommendation is to have at least 3 subnets per zone. 

Prod environment diagram