Right now clickhouse allows to create TTL columns for Distributed tables during alters. It is working normally until server restart. After that it won't start because engine distributed doesn't support TTL clause. Modify metadata is required.

My cluster has 21.3 but tested it also with 21.11 and the same behavior.
It is blocked during create but it should be also be blocked during alters.
Tested on table from tutorial
ENGINE = Distributed('stage, 'default', 'hits_v1') 
alter table hits_v1_all modify column UTMCampaign String TTL EventDate + INTERVAL 1 MONTH ← it passes normally
virtual bool scheduleDataProcessingJob(BackgroundJobsAssignee & assignee) = 0;
    
    bool scheduleDataMovingJob(BackgroundJobsAssignee & assignee);
    bool areBackgroundMovesNeeded() const;
    
    
    virtual void lockSharedData(const IMergeTreeDataPart &, bool = false) const {} 
    
    
    virtual bool unlockSharedData(const IMergeTreeDataPart &) const { return true; }
    
    virtual bool unlockSharedData(const IMergeTreeDataPart &, const String &) const { return true; }
    
    
    virtual bool tryToFetchIfShared(const IMergeTreeDataPart &, const DiskPtr &, const String &) { return false; }
    
    
    virtual bool removeDetachedPart(DiskPtr disk, const String & path, const String & part_name, bool is_freezed);
    
    
    virtual void createAndStoreFreezeMetadata(DiskPtr disk, DataPartPtr part, String backup_part_path) const;
    
    
    
    DataParts currently_submerging_big_parts;
    std::map<String, EmergingPartInfo> currently_emerging_big_parts;
    
    mutable std::mutex currently_submerging_emerging_mutex;
protected:
    friend class IMergeTreeDataPart;